Android應用程序與SurfaceFlinger服務是運行在不同的進程中的胡桨,因此瞬雹,它們采用Binder進程間通信機制來進行通信昧谊。
但是我們知道一個Android應用程序可能會有很多個窗口,而每一個窗口都有自己的UI元數(shù)據(jù)酗捌,因此呢诬,Android應用程序需要傳遞給SurfaceFlinger服務的UI元數(shù)據(jù)是相當可觀的。在這種情況下膛虫,通過Binder來在Android應用程序與SurfaceFlinger服務之間傳遞UI元數(shù)據(jù)是不合適的钓猬,因此這里選擇了Android系統(tǒng)的匿名共享內存的方案撩独。在每一個Android應用程序與SurfaceFlinger服務之間的連接上加上一塊用來傳遞UI元數(shù)據(jù)的匿名共享內存。而這塊區(qū)域被包裝為SharedClient综膀。
在每一個SharedClient里面,有至多31個SharedBufferStack,那什么又是SharedBufferStack橄登?
SharedBufferStack就是共享緩沖區(qū)堆棧讥此,每一個SharedBufferStack與一個Surface一一對應拢锹,每一個Surface又對應一個窗口萄喳,那就是一個應用程序內部最多可創(chuàng)建31個窗口。SharedBufferStack 內部包含N個緩沖buffer, 開篇介紹的雙緩沖(front buffer , back buffer) ,三緩沖(front buffer , back buffer, tripple buffer)充坑,有了它SurfaceFlinger服務就可以使用N個緩沖區(qū)技術來繪制UI了染突。
下面我們再來了解下SharedBufferStack的結構:
SharedBufferStack中分為空閑buffer和已使用的buffer。其中SharedBufferStack中的每一個已經(jīng)使用了的緩沖區(qū)都對應有一個GraphicBuffer也榄,用來描述真正的UI數(shù)據(jù)薪棒。
客戶端一次申請GraphicBuffer且將UI元數(shù)據(jù)寫入GraphicBuffer的流程:
當Android應用程序需要更新一個Surface的時候,它就會找到與它所對應的SharedBufferStack俐芯,并且從它的空閑緩沖區(qū)列表的尾部取出一個空閑的Buffer。我們假設這個取出來的空閑Buffer的編號為index吧史。接下來Android應用程序就請求SurfaceFlinger服務為這個編號為index的Buffer分配一個圖形緩沖區(qū)GraphicBuffer。SurfaceFlinger服務分配好圖形緩沖區(qū)GraphicBuffer之后吨述,會將它的編號設置為index,然后再將這個圖形緩沖區(qū)GraphicBuffer返回給Android應用程序訪問揣云。Android應用程序得到了SurfaceFlinger服務返回的圖形緩沖區(qū)GraphicBuffer之后,就在里面寫入UI數(shù)據(jù)刘莹。寫完之后焚刚,就將與它所對應的緩沖區(qū)点弯,即編號為index的Buffer矿咕,插入到對應的SharedBufferStack的已經(jīng)使用了的緩沖區(qū)列表的頭部去。這一步完成了之后捡絮,Android應用程序就通知SurfaceFlinger服務去繪制那些保存在已經(jīng)使用了的緩沖區(qū)所描述的圖形緩沖區(qū)GraphicBuffer了。
那么我們也知道一個繪圖表面锦援,在SurfaceFlinger服務和Android應用程序中分別對應Layer對象和Surface對象剥悟,其中這兩個對象在內部分別使用一個SharedBufferServer對象和一個SharedBufferClient對象來操作這個繪圖表面的UI元數(shù)據(jù)緩沖堆棧。操作過程如下:
在Android應用程序這一側区岗,當它需要渲染一個Surface時,它就會首先找到對應的SharedBufferClient對象叮称,然后再調用它的成員函數(shù)dequeue來請求分配一個UI元數(shù)據(jù)緩沖區(qū)藐鹤。有了這個UI元數(shù)據(jù)緩沖區(qū)之后,Android應用程序再調用這個SharedBufferClient對象的成員函數(shù)setDirtyRegion娱节、setCrop和setTransform來設置對應的Surface的裁剪區(qū)域、紋理坐標以及旋轉方向肄满。此外质涛,Android應用程序還會請求SurfaceFlinger服務為這個Surface分配一個圖形緩沖區(qū)掰担,以便可以往這個圖形緩沖區(qū)寫入實際的UI數(shù)據(jù)。最后带饱,Android應用程序就可以調用這個SharedBufferClient對象的成員函數(shù)queue把前面已經(jīng)準備好了的UI元數(shù)據(jù)緩沖區(qū)加入到它所描述的一個UI元數(shù)據(jù)緩沖區(qū)堆棧的待渲染隊列中,以便SurfaceFlinger服務可以在合適的時候對它進行渲染月趟。當SurfaceFlinger服務需要渲染一個Surface的時候恢口,它就會找到對應的一個SharedBufferServer對象穷躁,然后調用它的成員函數(shù)getQueueCount來檢查它所描述的一個UI元數(shù)據(jù)緩沖區(qū)堆棧的待渲染隊列的大小。如果這個大小大于0问潭,那么SurfaceFlinger服務就會繼續(xù)調用它的成員函數(shù)retireAndLock來取出隊列中的第一個UI元數(shù)據(jù)緩沖區(qū),以及調用它的成員函數(shù)getDirtyRegion狡忙、getCrop和getTransform來獲得要渲染的Surface的裁剪區(qū)域、紋理坐標和旋轉方向窜觉。最后北专,SurfaceFlinger服務就可以結合這些信息來將保存這個Surface的圖形緩沖區(qū)中的UI數(shù)據(jù)渲染在顯示屏中。
另外想深入了解BufferQueue的生產(chǎn)者消費者模型拓颓,詳細可以閱讀下如下這篇博文,感覺還不錯:https://blog.csdn.net/stn_lcd/article/details/73801313
參考:
https://blog.csdn.net/Luoshengyang/article/details/7867340