Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發實例 >> Android SurfaceFlinger中的工作線程:threadLoop()

Android SurfaceFlinger中的工作線程:threadLoop()

編輯:Android開發實例

SurfaceFlinger繼承了Thread類,自然也繼承了Thread類的threadLoop方法,SurfaceFlinger工作線程的主代碼都在threadLoop()方法中。工作線程啟動後,基類Thread會循環地調用threadLoop方法,SurfaceFlinger的threadLoop()主要是要完成系統中各個Layer(Surface)進行混合(compose),然後不停地把一幀幀混合好的圖像數據傳送到顯示設備中。

threadLoop的流程

                 圖一   threadLoop流程

1. handleConsoleEvents

handleConsoleEvent目前沒有深入了解,貌似只是處理顯示設備進入休眠狀態或者從休眠中喚醒時,改變SufaceFlinger的狀態,然後threadLoop的後續流程會根據相應的狀態來決定是否繼續給顯示設備傳送顯示數據。

2. handleTransaction

因為Layer的混合是在線程中進行的,而混合的過程中,應用程序或者系統可能會改變Layer的狀態,例如屏幕旋轉、增加或刪除Layer、某個Layer可見或不可見,為了使這些變動不會破壞當前正在進行的混合動作,SurfaceFlinger維護著兩個Layer列表:

  • mCurrentState.layersSortedByZ   ---- 當前系統最新的Layer列表
  • mDrawingState.layersSortedByZ  ---- 本次混合操作使用的Layer列表

handleTransaction就是根據Layer列表的這些狀態的變化,計算是否有可見區域內需要更新,並設置狀態變量mVisibleRegionsDirty,然後把mCurrentState賦值給mDrawingState,最後釋放已經被丟棄(ditch)的Layer

  • 上一次混合過程中,可能應用程序釋放了一個Layer,可是mDrawingState正在使用,不能馬上銷毀,所以要等到本次混合前才能做出銷毀的動作。

  • 如果Layer的大小有變化並且可見,Layer的handleTransaction將會重新分配緩沖區,並且凍結SurfaceFlinger後續的混合操作,也就是屏幕的內容本次將不會刷新,直到下一個循環的handlePageFlip階段才解除凍結。

3. handlePageFlip

該階段會遍歷各個Layer,在每個Layer中,取得並鎖住該Layer的frontBuffer,然後利用frontBuffer中的圖像數據生成該Layer的2D貼圖(Texture),並且計算更新區域,為後續的混合操作做准備。

                                圖二   handlePageFlip處理流程

Layer的lockPageFlip()首先通過SharedBufferServer類的成員變量lcblk,調用retireAndLock取得該Layer當前可用的frontBuffer,然後通過reloadTexture方法生成openGL ES的紋理貼圖,最後通過unlockPageFlip完成更新區域的Layer坐標到屏幕坐標的變換。

handleRepaint

 handleRepaint真正實現Layer混合的階段,下圖是handleRepaint的處理流程:

                                                     圖三  handleRepaint 的處理流程

handleRepaint首先重置了openGL的觀察矩陣,然後遍歷mDrawingState.layersSortedByZ 中的Layer列表,調用每個Layer的onDraw方法,在onDraw方法中,會調用drawWithOpenGL()方法,將在handlePageFlip階段生成的貼圖混合到OpenGL的主表面,最後handleRepaint把需要刷新的區域清除。

unlockClients

unlockClients只是遍歷各個Layer並調用各個Layer的finishPageFlip方法。finishPageFlip會進一步調用SharedBufferServer的unlock()方法:(關於SharedBufferSever,請參考本人以下博文的SharedClient 和 SharedBufferStack一節)

 

 
  1. void Layer::finishPageFlip()  
  2. {  
  3.     status_t err = lcblk->unlock( mFrontBufferIndex );  
  4.     LOGE_IF(err!=NO_ERROR,   
  5.             "layer %p, buffer=%d wasn't locked!",  
  6.             this, mFrontBufferIndex);  
  7. }  

 

 lcblk->unlock( mFrontBufferIndex )會把Layer的frontBuffer解除鎖定。

postFramebuffer

 進入postFramebuffer階段,OpenGL主表面已經准備好了混合完成的圖像數據,postFramebuffer只是簡單地調用hw.flip(),hw.flip()進一步調用了eglSwapBuffers完成主表面的切換,這樣屏幕上的圖像就會更新為新的數據。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved