Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發實例 >> Android SurfaceFlinger中的Layer,LayerDim,LayerBlur,LayerBuffer

Android SurfaceFlinger中的Layer,LayerDim,LayerBlur,LayerBuffer

編輯:Android開發實例

應用程序中不同類型的Surface,在FrameWorks本地層的SurfaceFlinger中,分別對應著不同的Layer類,本文主要是討論這幾種Layer的實現和差異。

閱讀本文之前,最好對SurfaceFlinger這個系統服務有所了解,可以參閱我的以下兩篇文章:

  • Android SurfaceFlinger中的SharedClient -- 客戶端(Surface)和服務端(Layer)之間的顯示緩沖區管理
  • Android SurfaceFlinger中的工作線程:threadLoop()

視覺效果

下面幾張圖片分別表示了不同Layer產生的視覺效果:

  • Layer對應普通的窗口
  • LayerDim 會使他後面的窗口產生一個變暗的透明效果
  • LayerBlur在LayerDim的基礎上,背景會產生模糊的效果

創建Layer

默認地,創建普通的窗口Surface,在SurfaceFlinger中會創建Layer類,如果想創建LayerDim或LayerBlur,應用程序需要在綁定View之前設置一下窗口的標志位:

創建LayerDim效果:

 

  1. @Override  
  2. protected void onCreate(Bundle icicle) {  
  3.     // Be sure to call the super class.  
  4.     super.onCreate(icicle);  
  5.  
  6.     // Have the system blur any windows behind this one.  
  7.     getWindow().setFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND,  
  8.             WindowManager.LayoutParams.FLAG_DIM_BEHIND);  
  9.     ......  
  10.     setContentView(......);  
 

 

創建LayerBlur效果:

 

  1. @Override  
  2. protected void onCreate(Bundle icicle) {  
  3.     // Be sure to call the super class.  
  4.     super.onCreate(icicle);  
  5.  
  6.     // Have the system blur any windows behind this one.  
  7.     getWindow().setFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND,  
  8.             WindowManager.LayoutParams.FLAG_BLUR_BEHIND);  
  9.     ......  
  10.     setContentView(......);  
 

 

相應地,在SufaceFlinger中,會根據Java層傳入的標志,創建不同的Layer:

  1. sp<ISurface> SurfaceFlinger::createSurface(ClientID clientId, int pid,  
  2.         const String8& name, ISurfaceFlingerClient::surface_data_t* params,  
  3.         DisplayID d, uint32_t w, uint32_t h, PixelFormat format,  
  4.         uint32_t flags)  
  5. {  
  6.     sp<LayerBaseClient> layer;  
  7.     sp<LayerBaseClient::Surface> surfaceHandle;  
  8.     ......  
  9.     switch (flags & eFXSurfaceMask) {  
  10.         case eFXSurfaceNormal:  
  11.             if (UNLIKELY(flags & ePushBuffers)) {  
  12.                 layer = createPushBuffersSurfaceLocked(client, d, id,  
  13.                         w, h, flags);  
  14.             } else {  
  15.                 layer = createNormalSurfaceLocked(client, d, id,  
  16.                         w, h, flags, format);  
  17.             }  
  18.             break;  
  19.         case eFXSurfaceBlur:  
  20.             layer = createBlurSurfaceLocked(client, d, id, w, h, flags);  
  21.             break;  
  22.         case eFXSurfaceDim:  
  23.             layer = createDimSurfaceLocked(client, d, id, w, h, flags);  
  24.             break;  
  25.     }  
  26.  
  27.     if (layer != 0) {  
  28.         layer->setName(name);  
  29.         setTransactionFlags(eTransactionNeeded);  
  30.         surfaceHandle = layer->getSurface();  
  31.         ........  
  32.     }  
  33.  
  34.     return surfaceHandle;  
  35. }  

 

 


Layer類的靜態結構

下面的圖展示了Layer類之間的繼承關系:

  • 所有的Layer都繼承了LayerBaseClient,SurfaceFlinger統一通過LayerBaseClient類訪問其他的派生Layer類
  • LayerBaseClient的內嵌類Surface繼承了ISurface接口,ISurface用於和SurfaceFlinger的客戶端交互
  • Layer和LayerBuffer都有各自的內嵌類:SurfaceLayer、SurfaceLayerBuffer,繼承了LayerBaseClient的內嵌類Surface
  •  LayerBuffer還有另外的內嵌類:Source,並且派生出另外兩個內嵌類:BufferSource、OverlaySource

ISurface接口

 ISurface接口其實非常簡單,只有幾個函數:

  • requestBuffer()        // Layer類使用,用於申請frontbuffer、backbuffer,初始化或size變化時調用
  • registerBuffers()      // LayerBuffer類使用,用於注冊IMemoryHeap接口
  • unregisterBuffers()  // LayerBuffer類使用,用於注銷IMemoryHeap接口
  • postBuffer()             // post用於刷新的圖像數據
  • createOverlay()       // 用於創建Overlay表面

LayerBaseClient的派生類中,會有一個內嵌類,繼承LayerBaseClient::Surface,然後根據需要會實現該接口的相應函數。


Layer類

Layer類是使用最多的一個,普通的應用程序窗口都會對應一個Layer類,Layer類的內嵌類SurfaceLayer繼承了ISurface接口,創建Layer類時,將會返回一個ISurface接口給創建者。並且,Layer類在創建時會建立兩個GraphicBuffer對象,這兩個Buffer在不同的時刻分別被作為frontbuffer和backbuffer,frontbuffer用於本窗口的畫圖操作,backbuffer用於所有窗口的混合操作。但是兩個GraphicBuffer對象在創建時並沒有真正地分配內存,而是在第一次lockBuffer時才正式通過ISurface接口的requestBuffer方法申請內存,當窗口的大小發生變化時,也要重新分配適合窗口大小的內存。Layer類的主要成員函數如下:

  • createSurface()  返回ISurface接口
  • setBuffers()  創建兩個GraphicBuffer對象,創建ISurface接口的實現類SurfaceLayer
  • onDraw()  把frontbuffer中的圖像數據通過OpenGL混合到OpenGL的主表面中
  • doTransaction()  檢測並處理窗口大小變化
  • lockPageFlip()  獲取frontbuffer,並且生成frontbuffer的OpenGL貼圖
  • finishPageFlip()  unlock frontbuffer,此後該buffer會queue到空閒列表中,下次可以作為backbuffer使用

LayerDim和LayerBlur

LayerDim和LayerBlur,他們的顯示內容是固定不變的(透明的黑色),所以不需要分配兩個GraphicBuffer對象,因此它們也沒有繼承自LayerBaseClient::Surface的內嵌類,而是直接使用LayerBaseClient::Surface類作為它們的ISurface接口。以LayerDim為例跟蹤一下它的Draw過程:

  • 創建LayerDim時,在LayerDim.initDimmer()中生成純黑的OpenGL貼圖

 

  1. void LayerDim::initDimmer(SurfaceFlinger* flinger, uint32_t w, uint32_t h)  
  2. {  
  3.     sTexId = -1;  
  4.     sImage = EGL_NO_IMAGE_KHR;  
  5.     ......  
  6.     if (LIKELY(flags & DisplayHardware::DIRECT_TEXTURE)) {  
  7.         /* 申請GraphicBuffer */ 
  8.         sp<GraphicBuffer> buffer = new GraphicBuffer(w, h, PIXEL_FORMAT_RGB_565,  
  9.                  GraphicBuffer::USAGE_SW_WRITE_OFTEN |  
  10.                  GraphicBuffer::USAGE_HW_TEXTURE);  
  11.           
  12.         android_native_buffer_t* clientBuf = buffer->getNativeBuffer();  
  13.        /* 申請OpenGL貼圖 */ 
  14.         glGenTextures(1, &sTexId);  
  15.         glBindTexture(GL_TEXTURE_2D, sTexId);  
  16.  
  17.         EGLDisplay dpy = eglGetCurrentDisplay();  
  18.         sImage = eglCreateImageKHR(dpy, EGL_NO_CONTEXT,   
  19.                 EGL_NATIVE_BUFFER_ANDROID, (EGLClientBuffer)clientBuf, 0);  
  20.         glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)sImage);  
  21.         ......   
  22.         // initialize the texture with zeros  
  23.         GGLSurface t;  
  24.         buffer->lock(&t, GRALLOC_USAGE_SW_WRITE_OFTEN);  
  25.         memset(t.data, 0, t.stride * t.height * 2);  
  26.         buffer->unlock();  
  27.         sUseTexture = true;  
  28.     }  
  29. }  
 

 

  • 在OnDraw()中把第一步生成的貼圖混合到OpenGL的主表面中

 

  1. void LayerDim::onDraw(const Region& clip) const 
  2. {  
  3.     const State& s(drawingState());  
  4.     Region::const_iterator it = clip.begin();  
  5.     Region::const_iterator const end = clip.end();  
  6.     if (s.alpha>0 && (it != end)) {  
  7.         const DisplayHardware& hw(graphicPlane(0).displayHardware());  
  8.         ......  
  9.         /* 設置透明值 */ 
  10.         glColor4x(0, 0, 0, alpha);  
  11.           
  12. #if defined(DIM_WITH_TEXTURE) && defined(EGL_ANDROID_image_native_buffer)  
  13.         if (sUseTexture) {  
  14.             glBindTexture(GL_TEXTURE_2D, sTexId);  
  15.             glEnable(GL_TEXTURE_2D);  
  16.             glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);  
  17.             const GLshort texCoords[4][2] = {  
  18.                     { 0,  0 },  
  19.                     { 0,  1 },  
  20.                     { 1,  1 },  
  21.                     { 1,  0 }  
  22.             };  
  23.             glMatrixMode(GL_TEXTURE);  
  24.             glLoadIdentity();  
  25.             glEnableClientState(GL_TEXTURE_COORD_ARRAY);  
  26.             glTexCoordPointer(2, GL_SHORT, 0, texCoords);  
  27.         } else 
  28. #endif  
  29.         {  
  30.             glDisable(GL_TEXTURE_2D);  
  31.         }  
  32.  
  33.         GLshort w = sWidth;  
  34.         GLshort h = sHeight;  
  35.         const GLshort vertices[4][2] = {  
  36.                 { 0, 0 },  
  37.                 { 0, h },  
  38.                 { w, h },  
  39.                 { w, 0 }  
  40.         };  
  41.         glVertexPointer(2, GL_SHORT, 0, vertices);  
  42.  
  43.         while (it != end) {  
  44.             const Rect& r = *it++;  
  45.             const GLint sy = fbHeight - (r.top + r.height());  
  46.             glScissor(r.left, sy, r.width(), r.height());  
  47.             glDrawArrays(GL_TRIANGLE_FAN, 0, 4);   
  48.         }  
  49.     }  
  50.     glDisableClientState(GL_TEXTURE_COORD_ARRAY);  
  51. }  
 

 

 


 

LayerBuffer


《未完待續》

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