SurfaceFlinger是Android multimedia的一個(gè)部分惰帽,在Android 的實(shí)現(xiàn)中它是一個(gè)service憨降,提供系統(tǒng)范圍內(nèi)的surface composer功能,它能夠?qū)⒏鞣N應(yīng)用程序的2D该酗、3D surface進(jìn)行組合授药。
背景
每個(gè)應(yīng)用程序可能對(duì)應(yīng)著一個(gè)或者多個(gè)圖形界面,而每個(gè)界面我們就稱(chēng)之為一個(gè)surface 呜魄,或者說(shuō)是window 悔叽,在上面的圖中我們能看到4 個(gè)surface ,一個(gè)是home 界面爵嗅,還有就是紅娇澎、綠、藍(lán)分別代表的3個(gè)surface 睹晒,而兩個(gè)button 實(shí)際是home surface 里面的內(nèi)容趟庄。我們需要考慮一下情況:
- 每個(gè)surface 在屏幕上有它的位置、大小册招,然后每個(gè)surface 里面還有要顯示的內(nèi)容
- 各個(gè)surface 之間可能有重疊
- 我們可以想象在屏幕平面的垂直方向還有一個(gè)Z 軸岔激,所有的surface 根據(jù)在Z 軸上的坐標(biāo)來(lái)確定前后,這樣就可以描述各個(gè)surface 之間的上下覆蓋關(guān)系了是掰,而這個(gè)在Z 軸上的順序虑鼎,圖形上有個(gè)專(zhuān)業(yè)術(shù)語(yǔ)叫Z-order 。
2.我們需要一個(gè)結(jié)構(gòu)來(lái)記錄應(yīng)用程序界面的位置键痛,大小炫彩,以及一個(gè)buffer 來(lái)記錄需要顯示的內(nèi)容,所以這就是我們 surface 的概念絮短,surface 實(shí)際我們可以把它理解成一個(gè)容器江兢,這個(gè)容器記錄著應(yīng)用程序界面的控制信息,比如說(shuō)大小丁频、位置杉允,而它還有buffer 來(lái)專(zhuān)門(mén)存儲(chǔ)需要顯示的內(nèi)容邑贴。 - 當(dāng)存在圖形重合或者有些surface 還帶有透明信息的時(shí)候,就需要 SurfaceFlinger 來(lái)解決問(wèn)題叔磷,它要把各個(gè)surface 組合(compose/merge)成一個(gè)main Surface 拢驾,最后將Main Surface 的內(nèi)容發(fā)送給FB/V4l2 Output ,這樣屏幕上就能看到我們想要的效果改基。
在實(shí)際中對(duì)這些Surface 進(jìn)行merge 可以采用兩種方式繁疤,一種就是采用軟件的形式來(lái)merge ,還一種就是采用硬件的方式秕狰,軟件的方式就是我們的SurfaceFlinger 稠腊,而硬件的方式就是Overlay 。
Overlay
因?yàn)橛布erge 內(nèi)容相對(duì)簡(jiǎn)單鸣哀,我們首先來(lái)看overlay 架忌。以IMX51 為例子,當(dāng)IPU 向內(nèi)核申請(qǐng)F(tuán)B 的時(shí)候它會(huì)申請(qǐng)3 個(gè)FB 诺舔,一個(gè)是主屏的鳖昌,還一個(gè)是副屏的,還一個(gè)就是Overlay 的低飒。 簡(jiǎn)單地來(lái)說(shuō)许昨,Overlay就是我們將硬件所能接受的格式數(shù)據(jù)和控制信息送到這個(gè)Overlay FrameBuffer,由硬件驅(qū)動(dòng)來(lái)負(fù)責(zé)merge Overlay buffer和主屏buffer中的內(nèi)容褥赊。
一般來(lái)說(shuō)現(xiàn)在的硬件都只支持一個(gè)Overlay糕档,主要用在視頻播放以及camera preview上,因?yàn)橐曨l內(nèi)容的不斷變化用硬件Merge比用軟件Merge要有效率得多拌喉,下面就是使用Overlay和不使用Overlay的過(guò)程:
SurfaceFlinger
surfaceFlinger 只是負(fù)責(zé) merge Surface 的控制速那,比如說(shuō)計(jì)算出兩個(gè) Surface 重疊的區(qū)域,至于 Surface 需要顯示的內(nèi)容尿背,則通過(guò) skia端仰,opengl 和 pixflinger 來(lái)計(jì)算。
創(chuàng)建過(guò)程
在IBinder 左邊的就是客戶(hù)端部分田藐,也就是需要窗口顯示的應(yīng)用程序荔烧,而右邊就是我們的 Surface Flinger service 。 創(chuàng)建一個(gè)surface 分為兩個(gè)過(guò)程汽久,一個(gè)是在 SurfaceFlinger 這邊為每個(gè)應(yīng)用程序(Client) 創(chuàng)建一個(gè)管理結(jié)構(gòu)鹤竭,另一個(gè)就是創(chuàng)建存儲(chǔ)內(nèi)容的buffer ,以及在這個(gè)buffer 上的一系列畫(huà)圖之類(lèi)的操作景醇。
-
創(chuàng)建Client
因?yàn)镾urfaceFlinger 要管理多個(gè)應(yīng)用程序的多個(gè)窗口界面臀稚,為了進(jìn)行管理它提供了一個(gè)Client 類(lèi),每個(gè)來(lái)請(qǐng)求服務(wù)的應(yīng)用程序就對(duì)應(yīng)了一個(gè) Client 三痰。因?yàn)?surface 是在 SurfaceFlinger 創(chuàng)建的吧寺,必須返回一個(gè)結(jié)構(gòu)讓?xiě)?yīng)用程序知道自己申請(qǐng)的 surface 信息窜管,因此 SurfaceFlinger 將 Client 創(chuàng)建的控制結(jié)構(gòu)per_client_cblk_t 經(jīng)過(guò) BClient 的封裝以后返回給 SurfaceComposerClient ,并向應(yīng)用程序提供了一組創(chuàng)建和銷(xiāo)毀 surface 的接口:
Flinger 為每個(gè) Client 提供了 8M 的空間微峰,包括控制信息和存儲(chǔ)內(nèi)容的 buffer 。
為應(yīng)用程序創(chuàng)建一個(gè) Client 以后抒钱,下面需要做的就是為這個(gè) Client 分配 Surface , 可以理解為創(chuàng)建一個(gè) Surface 就是創(chuàng)建一個(gè) Layer 颜凯。 -
創(chuàng)建 Layer
創(chuàng)建 Layer 的過(guò)程谋币,首先是由這個(gè)應(yīng)用程序的 Client 根據(jù)應(yīng)用程序的 pid 生成一個(gè)唯一的 layer ID ,然后根據(jù)大小症概、位置蕾额、格式等信息創(chuàng)建出 Layer 。在 Layer 里面有一個(gè)嵌套的 Surface 類(lèi)彼城,它主要包含一個(gè) ISurfaceFlingerClient::Surface_data_t 诅蝶,包含了這個(gè) Surace 的統(tǒng)一標(biāo)識(shí)符以及 buffer 信息等,提供給應(yīng)用程序使用募壕。最后應(yīng)用程序會(huì)根據(jù)返回來(lái)的 ISurface 創(chuàng)建一個(gè)自己的 Surface 调炬。
Android 提供了 4 種類(lèi)型的 layer 供選擇: Layer , LayerBlur 舱馅, LayerBuffer 缰泡, LayerDim ,每個(gè) layer 對(duì)應(yīng)一種類(lèi)型的窗口代嗤,并對(duì)應(yīng)這種窗口相應(yīng)的操作
- Normal Layer
它是 Android 種使用最多的一種 Layer 棘钞,一般的應(yīng)用程序在創(chuàng)建 surface 的時(shí)候都是采用的這樣的 layer , Normal Layer 為每個(gè) Surface 分配兩個(gè) buffer : front buffer 和 back buffer 干毅, Front buffer 用于 SurfaceFlinger 進(jìn)行顯示宜猜,而 Back buffer 用于應(yīng)用程序進(jìn)行畫(huà)圖,當(dāng) Back buffer 填滿(mǎn)數(shù)據(jù) (dirty) 以后硝逢,就會(huì) flip 姨拥, back buffer 就變成了 front buffer 用于顯示,而 front buffer 就變成了 back buffer 用來(lái)畫(huà)圖趴捅。 - LayerBuffer
最復(fù)雜的一個(gè) layer垫毙,它不具備 render buffer ,主要用在 camera preview / video playback 上拱绑。它提供了兩種實(shí)現(xiàn)方式综芥,一種就是 post buffer ,另外一種就是我們前面提到的 overlay 猎拨, Overlay 的接口實(shí)際上就是在這個(gè) layer 上實(shí)現(xiàn)的膀藐。不管是 overlay 還是 post buffer 都是指這個(gè) layer 的數(shù)據(jù)來(lái)源自其他地方屠阻,只是 post buffer 是通過(guò)軟件的方式最后還是將這個(gè) layer merge 主的 FB ,而 overlay 則是通過(guò)硬件 merge 的方式來(lái)實(shí)現(xiàn)额各。與這個(gè) layer 緊密聯(lián)系在一起的是 ISurface 這個(gè)接口国觉,通過(guò)它來(lái)注冊(cè)數(shù)據(jù)來(lái)源。用法如下:
// 要使用 Surfaceflinger 的服務(wù)必須先創(chuàng)建一個(gè) client
sp<SurfaceComposerClient> client = new SurfaceComposerClient();
// 然后向 Surfaceflinger 申請(qǐng)一個(gè) Surface 虾啦, surface 類(lèi)型為 PushBuffers
sp<Surface> surface = client->createSurface(getpid(), 0, 320, 240,
PIXEL_FORMAT_UNKNOWN, ISurfaceComposer::ePushBuffers);
// 然后取得 ISurface 這個(gè)接口麻诀, getISurface() 這個(gè)函數(shù)的調(diào)用時(shí)具有權(quán)限限制的,
// 必須在Surface.h 中打開(kāi): /framewoks/base/include/ui/Surface.h
sp<ISurface> isurface = Test::getISurface(surface);
//overlay 方式下就創(chuàng)建 overlay 傲醉,然后就可以使用 overlay 的接口了
sp<OverlayRef> ref = isurface->createOverlay(320, 240, PIXEL_FORMAT_RGB_565);
sp<Overlay> verlay = new Overlay(ref);
//post buffer 方式下蝇闭,首先要?jiǎng)?chuàng)建一個(gè) buffer ,然后將 buffer 注冊(cè)到 ISurface 上
ISurface::BufferHeap buffers(w, h, w, h,
PIXEL_FORMAT_YCbCr_420_SP,
transform,
0,
mHardware->getPreviewHeap());
mSurface->registerBuffers(buffers);
- 硬毕、應(yīng)用程序?qū)Υ翱诘目刂埔约爱?huà)圖
首先了解一下 SurfaceFlinger 這個(gè)服務(wù)的運(yùn)作方式:
SurfaceFlinger 是一個(gè)線程類(lèi)呻引,它繼承了 Thread 類(lèi)。當(dāng)創(chuàng)建 SurfaceFlinger 這個(gè)服務(wù)的時(shí)候會(huì)啟動(dòng)一個(gè) SurfaceFlinger 監(jiān)聽(tīng)線程吐咳,這個(gè)線程會(huì)一直等待事件的發(fā)生逻悠,比如說(shuō)需要進(jìn)行 sruface flip ,或者說(shuō)窗口位置大小發(fā)生了變化等韭脊,一旦產(chǎn)生這些事件童谒,SurfaceComposerClient 就會(huì)通過(guò) IBinder 發(fā)出信號(hào),這個(gè)線程就會(huì)結(jié)束等待處理這些事件沪羔,處理完成以后會(huì)繼續(xù)等待惠啄,如此循環(huán)。
SurfaceComposerClient 和 SurfaceFlinger 是通過(guò) SurfaceFlingerSynchro 這個(gè)類(lèi)來(lái)同步信號(hào)的任内,其實(shí)說(shuō)穿了就是一個(gè)條件變量撵渡。監(jiān)聽(tīng)線程等待條件的值一旦變成 OPEN 就結(jié)束等待并將條件置成 CLOSE 然后進(jìn)行事件處理,處理完成以后再繼續(xù)等待條件的值變成 OPEN 死嗦,而 Client 的Surface 一旦改變就通過(guò) IBinder 通知 SurfaceFlinger 將條件變量的值變成 OPEN 趋距,并喚醒等待的線程,這樣就通過(guò)線程類(lèi)和條件變量實(shí)現(xiàn)了一個(gè)動(dòng)態(tài)處理機(jī)制越除。
- 在對(duì) Surface 進(jìn)行畫(huà)圖之前必須鎖定 Surface 的 layer 节腐,實(shí)際上就是鎖定了 Layer_cblk_t 里的 swapstate 這個(gè)變量。SurfaceComposerClient 通過(guò)調(diào)用 lockSurface() 來(lái)鎖定 swapsate 的值來(lái)確定要使用哪個(gè) buffer 畫(huà)圖摘盆,如果 swapstate 是下面的值就會(huì)阻塞 Client 翼雀,
| value | usages |
| ------ | ------ |
| eNextFlipPending | we've used both buffers already, so we need to wait for one to become availlable. |
| eResizeRequested | the buffer we're going to acquire is being resized. Block until it is done. |
| eFlipRequested && eBusy: | he buffer we're going to acquire is currently in use by the server. |
| eInvalidSurface | this is a special case, we don't block in this case, we just return an error. | - 調(diào)用 unlockSurfaceAndPost() 來(lái)通知 SurfaceFlinger 進(jìn)行Flip『⒗蓿或者僅僅調(diào)用 unlockSurface() 而不通知 SurfaceFlinger 狼渊。
一般來(lái)說(shuō)畫(huà)圖的過(guò)程需要重繪 Surface 上的所有像素,因?yàn)橐话闱闆r下顯示過(guò)后的像素是不做保存的,不過(guò)也可以通過(guò)設(shè)定來(lái)保存一些像素狈邑,而只繪制部分像素城须,這里就涉及到像素的拷貝了,需要將Front buffer 的內(nèi)容拷貝到 Back buffer 米苹。在 SurfaceFlinger 服務(wù)實(shí)現(xiàn)中像素的拷貝是經(jīng)常需要進(jìn)行的操作糕伐,而且還可能涉及拷貝過(guò)程的轉(zhuǎn)換,比如說(shuō)屏幕的旋轉(zhuǎn)蘸嘶,翻轉(zhuǎn)等一系列操作良瞧。因此 Android 提供了拷貝像素的 hal ,這個(gè)也可能是我們將來(lái)需要實(shí)現(xiàn)的训唱,因?yàn)橛糜布瓿上袼氐目截愝喊约翱截愡^(guò)程中可能的矩陣變換等操作,比用 memcpy 要有效率而且節(jié)省資源雪情。這個(gè) HAL 頭文件在:/hardware/libhardware/hardware/include/copybit.h
窗口狀態(tài)變化的處理是一個(gè)很復(fù)雜的過(guò)程,SurfaceFlinger 只是執(zhí)行 Windows Manager 的指令你辣,由 Windows manager 來(lái)決定什么是偶改變大小巡通、位置、透明度舍哄、以及如何調(diào)整layer 之間的順序宴凉, SurfaceFlinger 僅僅只是執(zhí)行它的指令。
- SurfaceFlinger 的處理過(guò)程
前面已經(jīng)說(shuō)過(guò)了SurfaceFlinger 這個(gè)服務(wù)在創(chuàng)建的時(shí)候會(huì)啟動(dòng)一個(gè)監(jiān)聽(tīng)的線程表悬,這個(gè)線程負(fù)責(zé)每次窗口更新時(shí)候的處理弥锄。
Android 組合各個(gè)窗口的原理:Android 實(shí)際上是通過(guò)計(jì)算每一個(gè)窗口的可見(jiàn)區(qū)域,就是我們?cè)谄聊簧峡梢?jiàn)的窗口區(qū)域 ( 用 Android 的詞匯來(lái)說(shuō)就是 visibleRegionScreen ) 蟆沫,然后將各個(gè)窗口的可見(jiàn)區(qū)域畫(huà)到一個(gè)主 layer 的相應(yīng)部分籽暇,最后就拼接成了一個(gè)完整的屏幕,然后將主 layer 輸送到 FB 顯示饭庞。在將各個(gè)窗口可見(jiàn)區(qū)域畫(huà)到主 layer 過(guò)程中涉及到一個(gè)硬件實(shí)現(xiàn)和一個(gè)軟件實(shí)現(xiàn)的問(wèn)題戒悠,如果是軟件實(shí)現(xiàn)則通過(guò) Opengl 重新畫(huà)圖,其中還包括存在透明度的 alpha 計(jì)算舟山;如果實(shí)現(xiàn)了 copybit hal 的話绸狐,可以直接將窗口的這部分?jǐn)?shù)據(jù)直接拷貝過(guò)來(lái),并完成可能的旋轉(zhuǎn)累盗,翻轉(zhuǎn)寒矿,以及 alhpa計(jì)算等。
- handleConsoleEvent
當(dāng)接收到 signal 或者 singalEvent 事件以后若债,線程就停止等待開(kāi)始對(duì) Client 的請(qǐng)求進(jìn)行處理符相,第一個(gè)步驟是 handleConsoleEvent ,它會(huì)取得屏幕或者釋放屏幕蠢琳,只有取得屏幕的時(shí)候才能夠在屏幕上畫(huà)圖主巍。 - handleTransaction
因?yàn)?strong>窗口狀態(tài)的改變只能在一個(gè) Transaction 中進(jìn)行冠息。而窗口狀態(tài)的改變可能造成本窗口和其他窗口的可見(jiàn)區(qū)域變化,所以就必須重新來(lái)計(jì)算窗口的可見(jiàn)區(qū)域孕索。在這個(gè)處理子過(guò)程中 Android會(huì)根據(jù)標(biāo)志位來(lái)對(duì)所有 layer 進(jìn)行遍歷逛艰,一旦發(fā)現(xiàn)哪個(gè)窗口的狀態(tài)發(fā)生了變化就設(shè)置標(biāo)志位以在將來(lái)重新計(jì)算這個(gè)窗口的可見(jiàn)區(qū)域。在完成所有子 layer 的遍歷以后搞旭, Android 還會(huì)根據(jù)標(biāo)志位來(lái)處理主layer 散怖,舉個(gè)例子,比如說(shuō)傳感器感應(yīng)到手機(jī)橫過(guò)來(lái)了肄渗,會(huì)將窗口橫向顯示镇眷,此時(shí)就要重新設(shè)置主 layer 的方向。 - handlePageFlip
處理每個(gè)窗口 surface buffer 之間的翻轉(zhuǎn)翎嫡,根據(jù) layer_state_t 的 swapsate 來(lái)決定是否要翻轉(zhuǎn)欠动,當(dāng) swapsate 的值是 eNextFlipPending 是就會(huì)翻轉(zhuǎn)。處理完翻轉(zhuǎn)以后它會(huì)重新計(jì)算每個(gè) layer的可見(jiàn)區(qū)域惑申。 - handleRepaint
計(jì)算出每個(gè) layer 的可見(jiàn)區(qū)域以后具伍,這一步就是將所有可見(jiàn)區(qū)域的內(nèi)容畫(huà)到主 layer 的相應(yīng)部分了,也就是說(shuō)將各個(gè) surface buffer 里面相應(yīng)的內(nèi)容拷貝到主 layer 相應(yīng)的 buffer 圈驼,其中可能還涉及到alpha 運(yùn)算人芽,像素的翻轉(zhuǎn),旋轉(zhuǎn)等等操作绩脆,這里就像我前面說(shuō)的可以用硬件來(lái)實(shí)現(xiàn)也可以用軟件來(lái)實(shí)現(xiàn)萤厅。在使用軟件的 opengl 做計(jì)算的過(guò)程中還會(huì)用到 PixFlinger 來(lái)做像素的合成, - postFrameBuffer
翻轉(zhuǎn)主 layer 的兩個(gè) buffer 靴迫,將剛剛寫(xiě)入的內(nèi)容放入 FB 內(nèi)顯示了惕味。
共享內(nèi)存
普通的Android控件,例如TextView玉锌、Button和CheckBox等赦拘,它們都是將自己的UI繪制在宿主窗口的繪圖表面之上,這意味著它們的UI是在應(yīng)用程序的主線程中進(jìn)行繪制的。由于應(yīng)用程序的主線程除了要繪制UI之外,還需要及時(shí)地響應(yīng)用戶(hù)輸入系羞,否則系統(tǒng)就會(huì)認(rèn)為應(yīng)用程序沒(méi)有響應(yīng)了扭屁。而對(duì)于一些游戲畫(huà)面,或者攝像頭預(yù)覽、視頻播放來(lái)說(shuō),它們的UI都比較復(fù)雜,而且要求能夠進(jìn)行高效的繪制捎谨。這時(shí)候就必須要給那些需要復(fù)雜而高效UI的視圖生成一個(gè)獨(dú)立的繪圖表面,以及使用一個(gè)獨(dú)立的線程來(lái)繪制這些視圖的UI。
SurfaceFlinger服務(wù)運(yùn)行在Android系統(tǒng)的System進(jìn)程中涛救,它負(fù)責(zé)管理Android系統(tǒng)的幀緩沖區(qū)(Frame Buffer)畏邢。Android應(yīng)用程序?yàn)榱四軌驅(qū)⒆约旱腢I繪制在系統(tǒng)的幀緩沖區(qū)上,它們就必須要與SurfaceFlinger服務(wù)進(jìn)行通信检吆。
在APP端執(zhí)行draw的時(shí)候舒萎,數(shù)據(jù)很明顯是要繪制到APP的進(jìn)程空間,但是視圖窗口要經(jīng)過(guò)SurfaceFlinger圖層混排才會(huì)生成最終的幀蹭沛,而SurfaceFlinger又運(yùn)行在另一個(gè)獨(dú)立的服務(wù)進(jìn)程臂寝,那么View視圖的數(shù)據(jù)是如何在兩個(gè)進(jìn)程間傳遞的呢,普通的Binder通信肯定不行摊灭,因?yàn)锽inder不太適合這種數(shù)據(jù)量較大的通信咆贬,那么View數(shù)據(jù)的通信采用的是什么IPC手段呢?答案就是共享內(nèi)存帚呼,更精確的說(shuō)是匿名共享內(nèi)存掏缎。共享內(nèi)存是Linux自帶的一種IPC機(jī)制,Android直接使用了該模型煤杀,不過(guò)做出了自己的改進(jìn)眷蜈,進(jìn)而形成了Android的匿名共享內(nèi)存(Anonymous Shared Memory-Ashmem)。通過(guò)Ashmem怜珍,APP進(jìn)程同SurfaceFlinger共用一塊內(nèi)存,如此凤粗,就不需要進(jìn)行數(shù)據(jù)拷貝酥泛,APP端繪制完畢嫌拣,通知SurfaceFlinger端合成捶索,再輸出到硬件進(jìn)行顯示即可。
在每一個(gè)Android應(yīng)用程序與SurfaceFlinger服務(wù)之間的連接上加上一塊用來(lái)傳遞UI元數(shù)據(jù)的匿名共享內(nèi)存燎竖,這個(gè)共享內(nèi)存就是 SharedClient
在每一個(gè)SharedClient里面构回,有至多31個(gè)SharedBufferStack纤掸。SharedBufferStack就是Android應(yīng)用程序和SurfaceFlinger 的緩沖區(qū)堆棧政己。用來(lái)緩沖 UI 元數(shù)據(jù)。
一般我們就繪制UI的時(shí)候,都會(huì)采用一種稱(chēng)為“雙緩沖”的技術(shù)京腥。雙緩沖意味著要使用兩個(gè)緩沖區(qū),其中一個(gè)稱(chēng)為Front Buffer,另外一個(gè)稱(chēng)為Back Buffer。UI總是先在Back Buffer中繪制宜鸯,然后再和Front Buffer交換鸿市,渲染到顯示設(shè)備中剥懒。這下就可以理解SharedBufferStack的含義了吧谒获?SurfaceFlinger服務(wù)只不過(guò)是將傳統(tǒng)的“雙緩沖”技術(shù)升華和抽象為了一個(gè)SharedBufferStack∽Σ玻可別小看了這個(gè)升華和抽象榔昔,有了SharedBufferStack之后瘪菌,SurfaceFlinger 服務(wù)就可以使用N個(gè)緩沖區(qū)技術(shù)來(lái)繪制UI了撒会。N值的取值范圍為2到16。例如师妙,在Android 2.3中诵肛,N的值等于2,而在Android 4.1中默穴,據(jù)說(shuō)就等于3了怔檩。
在SurfaceFlinger服務(wù)中,每一個(gè)SharedBufferStack都對(duì)應(yīng)一個(gè)Surface壁顶,即一個(gè)窗口珠洗。這樣溜歪,我們就可以知道為什么每一個(gè)SharedClient里面包含的是一系列SharedBufferStack而不是單個(gè)SharedBufferStack:一個(gè)SharedClient對(duì)應(yīng)一個(gè)Android應(yīng)用程序若专,而一個(gè)Android應(yīng)用程序可能包含有多個(gè)窗口,即Surface蝴猪。從這里也可以看出调衰,一個(gè)Android應(yīng)用程序至多可以包含31個(gè)Surface。
我們假設(shè)圖中的SharedBufferStack有5個(gè)Buffer自阱,其中嚎莉,Buffer-1和Buffer-2是已經(jīng)使用了的,而B(niǎo)uffer-3沛豌、Buffer-4和Buffer-5是空閑的趋箩。指針head和tail分別指向空閑緩沖區(qū)列表的頭部和尾部赃额,而指針queue_head指向已經(jīng)使用了的緩沖區(qū)列表的頭部。從這里就可以看出叫确,從指針tail到head之間的Buffer即為空閑緩沖區(qū)表跳芳,而從指針head到queue_head之間的Buffer即為已經(jīng)使用了的緩沖區(qū)列表。注意竹勉,圖中的5個(gè)Buffer是循環(huán)使用的飞盆。
SharedBufferStack中的緩沖區(qū)只是用來(lái)描述UI元數(shù)據(jù)的,這意味著它們不包含真正的UI數(shù)據(jù)次乓。真正的UI數(shù)據(jù)保存在GraphicBuffer中吓歇,后面我們?cè)倜枋鯣aphicBuffer。因此票腰,為了完整地描述一個(gè)UI城看,SharedBufferStack中的每一個(gè)已經(jīng)使用了的緩沖區(qū)都對(duì)應(yīng)有一個(gè)GraphicBuffer,用來(lái)描述真正的UI數(shù)據(jù)丧慈。當(dāng)SurfaceFlinger服務(wù)緩制Buffer-1和Buffer-2的時(shí)候析命,就會(huì)找到與它們所對(duì)應(yīng)的GraphicBuffer,這樣就可以將對(duì)應(yīng)的UI繪制出來(lái)了逃默。
當(dāng)Android應(yīng)用程序需要更新一個(gè)Surface的時(shí)候鹃愤,它就會(huì)找到與它所對(duì)應(yīng)的SharedBufferStack,并且從它的空閑緩沖區(qū)列表的尾部取出一個(gè)空閑的Buffer完域。我們假設(shè)這個(gè)取出來(lái)的空閑Buffer的編號(hào)為index软吐。接下來(lái)Android應(yīng)用程序就請(qǐng)求SurfaceFlinger服務(wù)為這個(gè)編號(hào)為index的Buffer分配一個(gè)圖形緩沖區(qū)GraphicBuffer。
SurfaceFlinger 服務(wù)分配好圖形緩沖區(qū) GraphicBuffer 之后吟税,會(huì)將它的編號(hào)設(shè)置為 index凹耙,然后再將這個(gè)圖形緩沖區(qū) GraphicBuffer 返回給 Android 應(yīng)用程序訪問(wèn)。Android應(yīng)用程序得到了 SurfaceFlinger 服務(wù)返回的圖形緩沖區(qū) GraphicBuffer 之后肠仪,就在里面寫(xiě)入U(xiǎn)I數(shù)據(jù)肖抱。寫(xiě)完之后,就將與它所對(duì)應(yīng)的緩沖區(qū)异旧,即編號(hào)為 index 的 Buffer意述,插入到對(duì)應(yīng)的 SharedBufferStack 的已經(jīng)使用了的緩沖區(qū)列表的頭部去。這一步完成了之后吮蛹,Android 應(yīng)用程序就通知 SurfaceFlinger 服務(wù)去繪制那些保存在已經(jīng)使用了的緩沖區(qū)所描述的圖形緩沖區(qū)GraphicBuffer了荤崇。用上面例子來(lái)說(shuō),SurfaceFlinger服務(wù)需要繪制的是編號(hào)為1和2的Buffer所對(duì)應(yīng)的圖形緩沖區(qū)GraphicBuffer潮针。由于SurfaceFlinger服務(wù)知道編號(hào)為1和2的 Buffer 所對(duì)應(yīng)的圖形緩沖區(qū) GraphicBuffer 在哪里术荤,因此,Android 應(yīng)用程序只需要告訴 SurfaceFlinger 服務(wù)要繪制的 Buffer 的編號(hào)就OK了每篷。當(dāng)一個(gè)已經(jīng)被使用了的Buffer被繪制了之后瓣戚,它就重新變成一個(gè)空閑的 Buffer 了端圈。
SharedBufferStack 是在 Android 應(yīng)用程序和 SurfaceFlinger 服務(wù)之間共享的,但是子库,Android 應(yīng)用程序和 SurfaceFlinger 服務(wù)使用 SharedBufferStack 的方式是不一樣的枫笛,具體來(lái)說(shuō),就是 Android 應(yīng)用程序關(guān)心的是它里面的空閑緩沖區(qū)列表刚照,而 SurfaceFlinger 服務(wù)關(guān)心的是它里面的已經(jīng)使用了的緩沖區(qū)列表刑巧。從SurfaceFlinger服務(wù)的角度來(lái)看,保存在 SharedBufferStack中 的已經(jīng)使用了的緩沖區(qū)其實(shí)就是在排隊(duì)等待渲染无畔。
為了方便 SharedBufferStack 在 Android 應(yīng)用程序和 SurfaceFlinger 服務(wù)中的訪問(wèn)啊楚,Android 系統(tǒng)分別使用 SharedBufferClient 和 SharedBufferServer 來(lái)描述 SharedBufferStack ,其中浑彰,SharedBufferClient 用來(lái)在Android 應(yīng)用程序這一側(cè)訪問(wèn) SharedBufferStack 的空閑緩沖區(qū)列表恭理,而 SharedBufferServer 用來(lái)在SurfaceFlinger 服務(wù)這一側(cè)訪問(wèn) SharedBufferStack 的排隊(duì)緩沖區(qū)列表。
只要 SharedBufferStack 中的 available 的 buffer 的數(shù)量大于0郭变, SharedBufferClient 就會(huì)將指針 tail 往前移一步颜价,并且減少 available 的值,以便可以獲得一個(gè)空閑的 Buffer诉濒。當(dāng) Android 應(yīng)用程序往這個(gè)空閑的 Buffer 寫(xiě)入好數(shù)據(jù)之后周伦,它就會(huì)通過(guò) SharedBufferClient 來(lái)將它添加到 SharedBufferStack 中的排隊(duì)緩沖區(qū)列表的尾部去,即指針 queue_head 的下一個(gè)位置上未荒。
當(dāng) Android 應(yīng)用程序通知 SurfaceFlinger 服務(wù)更新UI的時(shí)候专挪,只要對(duì)應(yīng)的 SharedBufferStack 中的 queued 的緩沖區(qū)的數(shù)量大于0,SharedBufferServer 就會(huì)將指針 head 的下一個(gè)Buffer繪制出來(lái)片排,并且將指針 head 向前移一步寨腔,以及將 queued 的值減1。
參考:
https://blog.csdn.net/luoshengyang/article/details/7846923