青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

++wythern++

X presents Y for a better Z

[轉]Android SurfaceFlinger中的SharedClient -- 客戶端(Surface)和服務端(Layer)之間的顯示緩沖區(qū)管理

原文:
http://blog.csdn.net/droidphone/article/details/5972568


  SurfaceFlinger在系統(tǒng)啟動階段作為系統(tǒng)服務被加載。應用程序中的每個窗口,對應本地代碼中的Surface,而Surface又對應于 SurfaceFlinger中的各個Layer,SurfaceFlinger的主要作用是為這些Layer申請內存,根據(jù)應用程序的請求管理這些 Layer顯示、隱藏、重畫等操作,最終由SurfaceFlinger把所有的Layer組合到一起,顯示到顯示器上。當一個應用程序需要在一個 Surface上進行畫圖操作時,首先要拿到這個Surface在內存中的起始地址,而這塊內存是在SurfaceFlinger中分配的,因為 SurfaceFlinger和應用程序并不是運行在同一個進程中,如何在應用客戶端(Surface)和服務端(SurfaceFlinger - Layer)之間傳遞和同步顯示緩沖區(qū)?這正是本文要討論的內容。

Surface的創(chuàng)建過程

我們先看看Android如何創(chuàng)建一個Surface,下面的序列圖展示了整個創(chuàng)建過程。

                                                              圖一   Surface的創(chuàng)建過程

創(chuàng)建Surface的過程基本上分為兩步:

1. 建立SurfaceSession

第一步通常只執(zhí)行一次,目的是創(chuàng)建一個SurfaceComposerClient的實例,JAVA層通過JNI調用本地代碼,本地代碼創(chuàng)建一個 SurfaceComposerClient的實例,SurfaceComposerClient通過ISurfaceComposer接口調用 SurfaceFlinger的createConnection,SurfaceFlinger返回一個ISurfaceFlingerClient接 口給SurfaceComposerClient,在createConnection的過程中,SurfaceFlinger創(chuàng)建了用于管理緩沖區(qū)切換 的SharedClient,關于SharedClient我們下面再介紹,最后,本地層把SurfaceComposerClient的實例返回給 JAVA層,完成SurfaceSession的建立。

 

2. 利用SurfaceSession創(chuàng)建Surface

JAVA層通過JNI調用本地代碼Surface_Init(),本地代碼首先取得第一步創(chuàng)建的SurfaceComposerClient實例, 通過SurfaceComposerClient,調用ISurfaceFlingerClient接口的createSurface方法,進入 SurfaceFlinger,SurfaceFlinger根據(jù)參數(shù),創(chuàng)建不同類型的Layer,然后調用Layer的setBuffers()方法, 為該Layer創(chuàng)建了兩個緩沖區(qū),然后返回該Layer的ISurface接口,SurfaceComposerClient使用這個ISurface接 口創(chuàng)建一個SurfaceControl實例,并把這個SurfaceControl返回給JAVA層。

 

由此得到以下結果:

  • JAVA層的Surface實際上對應于本地層的SurfaceControl對象,以后本地代碼可以使用JAVA傳入的SurfaceControl對象,通過SurfaceControl的getSurface方法,獲得本地Surface對象;
  • Android為每個Surface分配了兩個圖形緩沖區(qū),以便實現(xiàn)Page-Flip的動作;
  • 建立SurfaceSession時,SurfaceFlinger創(chuàng)建了用于管理兩個圖形緩沖區(qū)切換的SharedClient對 象,SurfaceComposerClient可以通過ISurfaceFlingerClient接口的getControlBlock()方法獲得 這個SharedClient對象,查看SurfaceComposerClient的成員函數(shù)_init:

 

  1. void SurfaceComposerClient::_init(  
  2.         const sp<ISurfaceComposer>& sm, const sp<ISurfaceFlingerClient>& conn)  
  3. {  
  4.     ......  
  5.     mClient = conn;  
  6.     if (mClient == 0) {  
  7.         mStatus = NO_INIT;  
  8.         return;  
  9.     }  
  10.   
  11.     mControlMemory = mClient->getControlBlock();  
  12.     mSignalServer = sm;  
  13.     mControl = static_cast<SharedClient *>(mControlMemory->getBase());  
  14. }  

獲得Surface對應的顯示緩沖區(qū)

雖然在SurfaceFlinger在創(chuàng)建Layer時已經為每個Layer申請了兩個緩沖區(qū),但是此時在JAVA層并看不到這兩個緩沖 區(qū),JAVA層要想在Surface上進行畫圖操作,必須要先把其中的一個緩沖區(qū)綁定到Canvas中,然后所有對該Canvas的畫圖操作最后都會畫到 該緩沖區(qū)內。下圖展現(xiàn)了綁定緩沖區(qū)的過程:

                                                                            圖二  綁定緩沖區(qū)的過程

    開始在Surface畫圖前,Surface.java會先調用lockCanvas()來得到要進行畫圖操作的Canvas,lockCanvas會進 一步調用本地層的Surface_lockCanvas,本地代碼利用JAVA層傳入的SurfaceControl對象,通過getSurface() 取得本地層的Surface對象,接著調用該Surface對象的lock()方法,lock()返回了改Surface的信息,其中包括了可用緩沖區(qū)的 首地址vaddr,該vaddr在Android的2D圖形庫Skia中,創(chuàng)建了一個bitmap,然后通過Skia庫中Canvas的 API:Canvas.setBitmapDevice(bitmap),把該bitmap綁定到Canvas中,最后把這個Canvas返回給JAVA 層,這樣JAVA層就可以在該Canvas上進行畫圖操作,而這些畫圖操作最終都會畫在以vaddr為首地址的緩沖區(qū)中。

    再看看在Surface的lock()方法中做了什么:

  • dequeueBuffer(&backBuffer)獲取backBuffer
    • SharedBufferClient->dequeue()獲得當前空閑緩沖區(qū)的編號
    • 通過緩沖區(qū)編號獲得真正的GraphicBuffer:backBuffer
    • 如果還沒有對Layer中的buffer進行映射(Mapper),getBufferLocked通過ISurface接口重新重新映射
  • 獲取frontBuffer
  • 根據(jù)兩個Buffer的更新區(qū)域,把frontBuffer的內容拷貝到backBuffer中,這樣保證了兩個Buffer中顯示內容的同步
  • backBuffer->lock() 獲得backBuffer緩沖區(qū)的首地址vaddr
  • 通過info參數(shù)返回vaddr

釋放Surface對應的顯示緩沖區(qū)

畫圖完成后,要想把Surface的內容顯示到屏幕上,需要把Canvas中綁定的緩沖區(qū)釋放,并且把該緩沖區(qū)從變成可投遞(因為默認只有兩個 buffer,所以實際上就是變成了frontBuffer),SurfaceFlinger的工作線程會在適當?shù)乃⑿聲r刻,把系統(tǒng)中所有的 frontBuffer混合在一起,然后通過OpenGL刷新到屏幕上。下圖展現(xiàn)了解除綁定緩沖區(qū)的過程:

                                                                 圖三  解除綁定緩沖區(qū)的過程

  • JAVA層調用unlockCanvasAndPost
  • 進入本地代碼:Surface_unlockCanvasAndPost
  • 本地代碼利用JAVA層傳入的SurfaceControl對象,通過getSurface()取得本地層的Surface對象
  • 綁定一個空的bitmap到Canvas中
  • 調用Surface的unlockAndPost方法
    • 調用GraphicBuffer的unlock(),解鎖緩沖區(qū)
    • 在queueBuffer()調用了SharedBufferClient的queue(),把該緩沖區(qū)更新為可投遞狀態(tài)

SharedClient 和 SharedBufferStack

從前面的討論可以看到,Canvas綁定緩沖區(qū)時,要通過SharedBufferClient的dequeue方法取得空閑的緩沖區(qū),而解除綁定 并提交緩沖區(qū)投遞時,最后也要調用SharedBufferClient的queue方法通知SurfaceFlinger的工作線程。實際上,在 SurfaceFlinger里,每個Layer也會關聯(lián)一個SharedBufferServer,SurfaceFlinger的工作線程通過 SharedBufferServer管理著Layer的緩沖區(qū),在SurfaceComposerClient建立連接的階 段,SurfaceFlinger就已經為該連接創(chuàng)建了一個SharedClient 對象,SharedClient 對象中包含了一個SharedBufferStack數(shù)組,數(shù)組的大小是31,每當創(chuàng)建一個Surface,就會占用數(shù)組中的一個 SharedBufferStack,然后SurfaceComposerClient端的Surface會創(chuàng)建一個 SharedBufferClient和該SharedBufferStack關聯(lián),而SurfaceFlinger端的Layer也會創(chuàng)建 SharedBufferServer和SharedBufferStack關聯(lián),實際上每對 SharedBufferClient/SharedBufferServer是控制著同一個SharedBufferStack對象,通過 SharedBufferStack,保證了負責對Surface的畫圖操作的應用端和負責刷新屏幕的服務端(SurfaceFlinger)可以使用不 同的緩沖區(qū),并且讓他們之間知道對方何時鎖定/釋放緩沖區(qū)。

SharedClient和SharedBufferStack的代碼和頭文件分別位于:

/frameworks/base/libs/surfaceflinger_client/SharedBufferStack.cpp

/frameworks/base/include/private/surfaceflinger/SharedBufferStack.h

 

 

                                                                       圖四    客戶端和服務端緩沖區(qū)管理

     繼續(xù)研究SharedClient、SharedBufferStack、SharedBufferClient、SharedBufferServer的誕生過程。

    1. SharedClient

  •     在createConnection階段,SurfaceFlinger創(chuàng)建Client對象:
  1. sp<ISurfaceFlingerClient> SurfaceFlinger::createConnection()  
  2. {  
  3.     Mutex::Autolock _l(mStateLock);  
  4.     uint32_t token = mTokens.acquire();  
  5.   
  6.     sp<Client> client = new Client(token, this);  
  7.     if (client->ctrlblk == 0) {  
  8.         mTokens.release(token);  
  9.         return 0;  
  10.     }  
  11.     status_t err = mClientsMap.add(token, client);  
  12.     if (err < 0) {  
  13.         mTokens.release(token);  
  14.         return 0;  
  15.     }  
  16.     sp<BClient> bclient =  
  17.         new BClient(this, token, client->getControlBlockMemory());  
  18.     return bclient;  
  19. }  
  • 再進入Client的構造函數(shù)中,它分配了4K大小的共享內存,并在這塊內存上構建了SharedClient對象:
  1. Client::Client(ClientID clientID, const sp<SurfaceFlinger>& flinger)  
  2.     : ctrlblk(0), cid(clientID), mPid(0), mBitmap(0), mFlinger(flinger)  
  3. {  
  4.     const int pgsize = getpagesize();  
  5.     const int cblksize = ((sizeof(SharedClient)+(pgsize-1))&~(pgsize-1));  
  6.   
  7.     mCblkHeap = new MemoryHeapBase(cblksize, 0,  
  8.             "SurfaceFlinger Client control-block");  
  9.   
  10.     ctrlblk = static_cast<SharedClient *>(mCblkHeap->getBase());  
  11.     if (ctrlblk) { // construct the shared structure in-place.  
  12.         new(ctrlblk) SharedClient;  
  13.     }  
  14. }  
  • 回到createConnection中,通過Client的getControlBlockMemory()方法獲得共享內存塊的 IMemoryHeap接口,接著創(chuàng)建ISurfaceFlingerClient的子類BClient,BClient的成員變量mCblk保存了 IMemoryHeap接口指針;
  • 把BClient返回給SurfaceComposerClient,SurfaceComposerClient通過 ISurfaceFlingerClient接口的getControlBlock()方法獲得IMemoryHeap接口指針,同時保存在 SurfaceComposerClient的成員變量mControlMemory中;
  • 繼續(xù)通過IMemoryHeap接口的getBase ()方法獲取共享內存的首地址,轉換為SharedClient指針后保存在SurfaceComposerClient的成員變量mControl中;
  • 至此,SurfaceComposerClient的成員變量mControl和SurfaceFlinger::Client.ctrlblk指向了同一個內存塊,該內存塊上就是SharedClient對象。 

    2. SharedBufferStack、SharedBufferServer、SharedBufferClient

    SharedClient對象中有一個SharedBufferStack數(shù)組:

    SharedBufferStack surfaces[ NUM_LAYERS_MAX ];

    NUM_LAYERS_MAX 被定義為31,這樣保證了SharedClient對象的大小正好滿足4KB的要求。創(chuàng)建一個新的Surface時,進入SurfaceFlinger的 createSurface函數(shù)后,先取在createConnection階段創(chuàng)建的Client對象,通過Client在 0--NUM_LAYERS_MAX 之間取得一個尚未被使用的編號,這個編號實際上就是SharedBufferStack數(shù)組的索引:

  1. int32_t id = client->generateId(pid);  
  

 然后以Client對象和索引值以及其他參數(shù),創(chuàng)建不同類型的Layer對象,一普通的Layer對象為例:

  1. layer = createNormalSurfaceLocked(client, d, id,  
  2.                         w, h, flags, format);  

在createNormalSurfaceLocked中創(chuàng)建Layer對象:

  1. sp<Layer> layer = new Layer(this, display, client, id);  

構造Layer時會先構造的父類LayerBaseClient,LayerBaseClient中創(chuàng)建了SharedBufferServer對 象,SharedBufferStack 數(shù)組的索引值和SharedClient被傳入SharedBufferServer對象中。

  1. LayerBaseClient::LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,  
  2.         const sp<Client>& client, int32_t i)  
  3.     : LayerBase(flinger, display), lcblk(NULL), client(client), mIndex(i),  
  4.       mIdentity(uint32_t(android_atomic_inc(&sIdentity)))  
  5. {  
  6.     lcblk = new SharedBufferServer(  
  7.             client->ctrlblk, i, NUM_BUFFERS,  
  8.             mIdentity);  
  9. }  

 

    自此,Layer通過lcblk成員變量(SharedBufferServer)和SharedClient共享內存區(qū)建立了關聯(lián),并且每個Layer對應于SharedBufferStack 數(shù)組中的一項。

    回到SurfaceFlinger的客戶端Surface.cpp中,Surface的構造函數(shù)如下:

  1. Surface::Surface(const sp<SurfaceControl>& surface)  
  2.     : mClient(surface->mClient), mSurface(surface->mSurface),  
  3.       mToken(surface->mToken), mIdentity(surface->mIdentity),  
  4.       mFormat(surface->mFormat), mFlags(surface->mFlags),  
  5.       mBufferMapper(GraphicBufferMapper::get()), mSharedBufferClient(NULL),  
  6.       mWidth(surface->mWidth), mHeight(surface->mHeight)  
  7. {  
  8.     mSharedBufferClient = new SharedBufferClient(  
  9.             mClient->mControl, mToken, 2, mIdentity);  
  10.   
  11.     init();  
  12. }  

SharedBufferClient構造參數(shù)mClient->mControl就是共享內存塊中的SharedClient對象,mToken就是SharedBufferStack 數(shù)組索引值。

到這里我們終于知道,Surface中的mSharedBufferClient成 員和Layer中的lcblk成員(SharedBufferServer),通過SharedClient中的同一個 SharedBufferStack,共同管理著Surface(Layer)中的兩個緩沖區(qū)。



一并參考:

http://wenku.baidu.com/view/0243844bc850ad02de8041e6.html

 

posted on 2011-11-05 20:47 wythern 閱讀(434) 評論(0)  編輯 收藏 引用

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            久久综合激情| 亚洲国产欧美久久| 一本久久综合亚洲鲁鲁| 久久五月婷婷丁香社区| 亚洲资源在线观看| 欧美日韩在线观看一区二区三区| 亚洲第一精品福利| 美女精品在线| 久久福利电影| 亚洲色图在线视频| 久久久午夜视频| 欧美日韩国产免费观看| 久久精品视频免费| 欧美日韩亚洲激情| 亚洲美女中文字幕| 亚洲综合日本| 亚洲自拍偷拍一区| 欧美日本簧片| 日韩小视频在线观看专区| 亚洲成人在线| 久久亚洲精品一区二区| 国产精品一区二区三区四区| 欧美激情无毛| 香港久久久电影| 伊人久久大香线蕉综合热线 | 另类专区欧美制服同性| 欧美日韩成人在线| 久久亚洲综合色| 亚洲九九精品| 国产综合色一区二区三区| 在线午夜精品自拍| 欧美影院一区| 亚洲欧美精品伊人久久| 亚洲国产一区二区三区在线播 | 久久综合久久综合这里只有精品| 中文在线一区| 国产自产精品| 欧美激情综合网| 亚洲日本成人| 一区二区免费在线视频| 国产综合香蕉五月婷在线| 亚洲午夜免费福利视频| 亚洲国产美女精品久久久久∴| 欧美一区二区三区在线看| 亚洲欧美在线一区| 国产亚洲一区二区三区| 欧美激情精品久久久久久蜜臀| 国产精品女主播| 免费成人性网站| 免费视频一区| 欧美ed2k| 亚洲精品老司机| 亚洲欧洲综合| 精品白丝av| 久久亚洲视频| 久久全球大尺度高清视频| 一区二区日韩欧美| 日韩午夜精品| 亚洲伊人伊色伊影伊综合网| 亚洲麻豆视频| 欧美一区二区黄| 狠狠色狠色综合曰曰| 国产精品久久久久久模特| 麻豆久久婷婷| 久久这里有精品视频| 欧美精品在线一区二区| 欧美jizz19hd性欧美| 亚洲欧美一区二区原创| 欧美激情精品久久久久久免费印度| 国内精品视频在线观看| 久久影视三级福利片| 一区二区动漫| 欧美高清免费| 国精品一区二区三区| 在线观看精品视频| 极品少妇一区二区| 亚洲国产一区二区三区在线播| 亚洲日本黄色| 亚洲大胆人体在线| 亚洲在线视频网站| 午夜久久久久久| 日韩视频第一页| 激情综合色综合久久| 一区二区三区视频免费在线观看| 99在线精品视频| 欧美在线视频日韩| 欧美一区网站| 91久久精品国产91性色tv| 欧美不卡视频一区| 久久国产一区| 在线亚洲一区二区| 亚洲欧美日韩国产综合精品二区| 欧美日韩在线一区二区三区| 亚洲国产成人在线视频| 亚洲黑丝在线| 亚洲国产日本| 亚洲小视频在线观看| 欧美xart系列高清| 国产精品女人毛片| 久久久国产一区二区| 午夜精品视频在线观看| 欧美黄在线观看| 国产精品一区二区久久精品| 久久久久久久久久久久久女国产乱 | 日韩天堂av| 亚洲国产成人久久| 国产精品日韩久久久| 奶水喷射视频一区| 欧美亚洲午夜视频在线观看| 亚洲乱码国产乱码精品精天堂| 欧美ed2k| 免费视频亚洲| 国产精品区一区二区三| 久久精品亚洲一区二区三区浴池| 伊人成人网在线看| 午夜一区在线| 99亚洲伊人久久精品影院红桃| 一区二区在线视频播放| 亚洲精品国产精品国自产观看浪潮| 国产精品久久久久9999高清| 欧美专区第一页| 欧美亚州韩日在线看免费版国语版| 老色批av在线精品| 欧美激情中文字幕在线| 亚洲精选成人| 久久亚洲精选| 亚洲欧洲精品一区二区| 国产精品久久久久婷婷| 久久蜜臀精品av| 国产一区二区无遮挡| 最新日韩欧美| 亚洲剧情一区二区| 亚洲先锋成人| 国产一区二区日韩精品| 欧美一区二区三区在线播放| 亚洲激情图片小说视频| 亚洲日本欧美在线| 亚洲高清在线| 美日韩丰满少妇在线观看| 一区二区三区国产精品| 久久青草福利网站| 伊人狠狠色丁香综合尤物| 欧美激情一区二区三级高清视频| 一本色道婷婷久久欧美| 亚洲精品偷拍| 欧美精品高清视频| 欧美肥婆在线| 国产主播喷水一区二区| 老鸭窝毛片一区二区三区| 鲁大师影院一区二区三区| 亚洲欧美激情视频| 欧美午夜精品久久久| 午夜在线a亚洲v天堂网2018| 亚洲视频电影在线| 欧美色图麻豆| 国产精品久久久久久久久免费桃花 | 亚洲精品在线一区二区| 国产亚洲电影| 亚洲欧洲精品一区二区三区 | 久久久蜜臀国产一区二区| 亚洲少妇自拍| 国产精品亚洲美女av网站| 久久视频一区| 久久国产精品黑丝| 亚洲网站在线观看| 欧美综合二区| 亚洲美女黄色| 永久久久久久| 国产欧美日韩三级| 久久爱www久久做| 亚洲一区二区三区在线播放| 欧美大片免费观看| 亚洲欧美日本日韩| 欧美性猛交xxxx乱大交退制版| 一本色道久久综合亚洲精品按摩 | 一区二区三区产品免费精品久久75 | 欧美在线视频观看| 亚洲成人中文| 激情欧美国产欧美| 国产精品综合| 国产精品日韩一区二区三区| 欧美激情亚洲| 国产精品免费网站在线观看| 欧美激情第六页| 久久久精品五月天| 国产精品videosex极品| 亚洲福利国产| 美女精品在线观看| 亚洲精品乱码久久久久久按摩观| 亚洲欧美卡通另类91av| 国产精品免费观看视频| 亚洲国产欧美一区| 模特精品在线| 欧美激情一区二区三区全黄| 欧美二区在线看| 亚洲精品国产精品乱码不99按摩| 亚洲国产一二三| 欧美一区二区三区视频免费| 欧美1区2区| 欧美性猛交xxxx乱大交退制版|