1.android視窗系統通過c-s架構和一套buffer循環機制實作,在保證安全穩定的前提下基本上做到了極緻性能(無大塊記憶體拷貝,ipc通信内容最少)。
2.surfaceflinger建立layer,将其中的bufferqueueproducer作為igraphicbufferproducer傳給應用側的surface,因而構成視窗。
3.surface是皮,bufferqueue是肉,通過這樣的皮肉關系建構了buffer循環機制。buffer循環機制不僅用于視窗系統,也用于視訊播放解碼流,相機拍照資料流等(camera2.0架構)。
注:代碼基于android 5.0
作為一個應用,繪圖是自由的,基本上也是平台無關的。但如果要把繪圖的結果顯示出來,就必須依賴平台提供的視窗系統。好比我們寫篇文章出來容易,要投到雜志上發表,就必須按雜志社的格式,并通過審校等一堆流程,不然每個人都随便發,肯定亂套了。

android為應用層提供的視窗接口為anativewindow。這個接口可用來調整配置參數,擷取圖形記憶體并送還觸發顯示。應用層是buffer的生産者。
對于非gpu繪圖的應用,通過這個類去擷取圖形記憶體(dequeuebuffer),并在繪制完成之後送還(queuebuffer),讓顯示系統在合适的時機顯示。
對于gpu繪圖(嚴格來說,是使用egl标準)的應用,在建立opengl上下文時将anativewindow的指針傳入,gpu的驅動會在合适的時候完成擷取記憶體和送還的操作。應用層隻需要調用eglswapbuffers換緩存即可。
對應用層開放的windows接口定義在
system/core/include/system/windows.h
主要接口函數如下:
用于perform和query接口的一些宏定義如下:
自android 4.2之後,framebuffernativewindow被廢棄,所有視窗均繼承surface。surface本身是一種anativewindow。
用于圖形顯示的視窗,是由surfaceflinger程序負責建立的:
為應用層建立surface(視窗)時,surfaceflinger同步建立一個layer,并将layer的生産者關聯到surface上。這樣,應用側便可以通過surface申請buffer,作為生産者渲染圖像,送顯由layer中的消費者負責。
對于按一定幀率重新整理的視窗系統,每一次渲染隻有很有限的時間,頻繁地申請/釋放圖形記憶體是不可接受的。android的做法是維護一個buffer隊列,按生産者——消費者模式循環利用。這個buffer就是上一章所述的graphicbuffer。
buffer隊列池中持有固定數量的buffer(由setbuffercount函數決定,一般是3塊),每個buffer有四種狀态,決定其是否可以被生産者/消費者通路。
由于layer位于surfaceflinger程序中,graphicbuffer是在surfaceflinger程序中建立的。應用層作為生産者,使用時需要将其映射到自己的程序空間。在每次申請buffer時都做一次映射很不明智。
很容易想到的一個方法是在應用層建一個graphicbuffer隊列,和surfaceflinger中的buffer隊列對應地映射起來,每次申請和返還時,以序号代替真實的graphicbuffer傳替。android也正是這麼做的。
surface::dequeuebuffer(android_native_buffer_t** buffer, int* fencefd)
這接口用于申請記憶體進行生産(渲染)。
于surface側,它擷取buffer的序列号,然後檢查是否已經同步過,若沒有同步過調用requestbuffer同步(映射共享記憶體)。
于bufferqueue側,它檢查是否有 free 标志的buffer,如果沒有,根據 mproducercontrolledbyapp 标志決定傳回錯誤碼或者等待。
fencefd是bufferqueue傳回給surface的,生産者有義務去等fence。
int surface::queuebuffer(android_native_buffer_t* buffer, int fencefd)
于surface側,它将buffer送還給bufferqueue,但這不一定表示生産者用完了,消費者擷取到buffer之後仍有義務等fence。
于bufferqueue側,接收到buffer,将其放到一個可用隊列中,修改狀态,并且觸發監聽器的onframeavailable函數。
消費者擷取buffer,由于在queuebuffer時,會将buffer放到一個隊列中,這時便從那個隊列去取。
消費者釋放buffer。