1 Surfaceflinger線程
Surfaceflinger是一個類,同時又是線程,該線程通過迴圈,不斷計算並重新整理當前螢幕需要的顯示內容。Surfaceflinger線程屬於SystemServer進程,也就是在SystemServer進程中啟動了Surfaceflinger線程。
Surfaceflinger中儲存著各種layer,其主要工作就是負責各種layer的融合,因此可看做一個用於維護各種layer的線程。
啟
動Android線程需要提供兩個介面,一是readyToRun(),該函數定義了線程迴圈前需要初始化的內容;二是threadLoop(),每個線
程都必須實現,該函數定義了線程執行的內容,如果該函數返回true,線程會繼續調用threadLoop(),如果返回false,線程將退出。
2 初始化
Surfaceflinger類的建構函式會執行init(),該函數輸出Surfaceflinger啟動資訊,並配置一些調試資訊。接著執行readyToRun(),初始化整個顯示系統。
readyToRun()調用過程如下:
(1)執行new DisplayHardware(this, dpy),通過DisplayHardware初始化Framebuffer、EGL並擷取OpenGL ES資訊。
(2)建立共用的記憶體控制塊。
(3)將EGL與當前螢幕綁定。
(4)初始化共用記憶體控制塊。
(5)初始化OpenGL ES。
(6)顯示開機動畫。
3 核心資料結構
State mCurrentState;
當前更新的狀態
State mDrawingState;
正在螢幕上繪製的狀態
LayerVector layersSortedByZ;
儲存layer的列表,類似於Z軸,mCurrentState和mDrawingState分別擁有一個列表。
4 主迴圈threadLoop()
通過流程圖可以看到threadLoop()都做了哪些操作。
4.1 waitForEvent函數
waitForEvent函數將逾時時間設定為5秒鐘,並等待系統事件發生。在逾時前若有事件發生則立即返回,若發生逾時將輸出警告資訊,上層一般會處理這個問題。
4.2 handleConsoleEvents函數
該函數被執行的幾率較低,主要用於處理控制台事件。
4.3 handleTransaction函數
該函數將遍曆Surfaceflinger擁有的每一個layer,檢查是否有layer的屬性改變,主要執行以下工作:
(1)擷取mCurrentState.layersSortedByZ及layer的數目。
(2)遍曆所有layer,擷取layer對應的參數,判斷是否有layer的屬性改變和是否有需要顯示的layer。
(3)更新主畫面參數:
如果螢幕需要旋轉,則需更新所有可見地區和共用控制塊,並計算旋轉參數;
判斷主畫面是否需要被凍結;
判斷是否有新加入的layer;
去除不再需要的layer,通過ditchedLayers.add(layer)釋放資源;
(4)通過廣播更新所有改變。
4.4 handlePageFlip函數
該函數主統計所有layer的資訊,針對需要的layer進行重繪,並計算螢幕實際可顯示地區。
(1)調用lockPageFlip(currentLayers)
遍
曆currentLayers包含的所有layer,依次調用每層layer對應的lockPageFlip函數。首先通過retireAndLock函
數取得新的frontbuffer,然後擷取並計算髒的地區,最後調用reloadTexture函數更新這些地區。
(2)
如果有需要顯示的layer,調用computeVisibleRegionsFunction Compute經過混合後每個layer的顯示地區。每一個layer擁有三片區
域,分別為opaqueRegion、visibleRegion和coveredRegion,主畫面則擁有aboveOpaqueLayers、
aboveCoveredLayers。在遍曆每一層layer時,要計算沒個layer對應的地區,同時同步更新主畫面的
aboveOpaqueLayers和aboveCoveredLayers。
(3)調用unlockPageFlip(currentLayers)
遍曆currentLayers包含的所有layer,依次調用每層layer對應的unlockPageFlip函數,完成layer到螢幕的座標變換。
4.5 handleRepaint函數
handlePageFlip更新並計算每一個獨立layer的顯示地區,handleRepaint則負責將每一個layer經過計算的顯示地區資料搬運至螢幕的顯存中。
(1)根據不同的螢幕類型,設定更新模式,有部分更新、緩衝更新、矩形框交換和全屏更新。
(2)調用composeSurfaces(mDirtyRegion)
該函數將遍曆每一層layer,調用layer對應的onDraw介面,將資料從layer的緩衝搬運至螢幕的顯存中。
4.6 hw.compositionComplete函數
該函數會調用到gralloc模組的fb_compositionComplete介面,是提供給螢幕的回調介面,目前並沒有實現任何功能,根據採用螢幕的不同可能需要填充相應操作。
4.7 unlockClients函數
unlockClients函數將遍曆每一層layer,調用finishPageFlip釋放layer用於的共用控制塊。
4.8 postFramebuffer函數
handleRepaint函數執行的搬運操作實際將顯示資料搬運至螢幕的後緩衝中,postFramebuffer最終將調用到eglSwapBuffers(dpy, surface),交換螢幕的後緩衝和前緩衝,實現顯示更新。
4.9 另一條路線
如果hw.canDraw返回錯誤或者螢幕此時被凍結,那麼將無法進行資料更新,此時將都另外一條路線,直接調用unlockClients,並休眠16667微秒。如果顯示出現問題,16667微秒將保證每秒最多執行60次threadLoop函數。