• <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>

            ++wythern++

            X presents Y for a better Z

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

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


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

            Surface的創(chuàng)建過程

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

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

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

            1. 建立SurfaceSession

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

             

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

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

             

            由此得到以下結(jié)果:

            • JAVA層的Surface實(shí)際上對(duì)應(yīng)于本地層的SurfaceControl對(duì)象,以后本地代碼可以使用JAVA傳入的SurfaceControl對(duì)象,通過SurfaceControl的getSurface方法,獲得本地Surface對(duì)象;
            • Android為每個(gè)Surface分配了兩個(gè)圖形緩沖區(qū),以便實(shí)現(xiàn)Page-Flip的動(dòng)作;
            • 建立SurfaceSession時(shí),SurfaceFlinger創(chuàng)建了用于管理兩個(gè)圖形緩沖區(qū)切換的SharedClient對(duì) 象,SurfaceComposerClient可以通過ISurfaceFlingerClient接口的getControlBlock()方法獲得 這個(gè)SharedClient對(duì)象,查看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對(duì)應(yīng)的顯示緩沖區(qū)

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

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

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

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

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

            釋放Surface對(duì)應(yīng)的顯示緩沖區(qū)

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

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

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

            SharedClient 和 SharedBufferStack

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

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

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

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

             

             

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

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

                1. SharedClient

            •     在createConnection階段,SurfaceFlinger創(chuàng)建Client對(duì)象:
            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. }  
            • 再進(jìn)入Client的構(gòu)造函數(shù)中,它分配了4K大小的共享內(nèi)存,并在這塊內(nèi)存上構(gòu)建了SharedClient對(duì)象:
            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()方法獲得共享內(nèi)存塊的 IMemoryHeap接口,接著創(chuàng)建ISurfaceFlingerClient的子類BClient,BClient的成員變量mCblk保存了 IMemoryHeap接口指針;
            • 把BClient返回給SurfaceComposerClient,SurfaceComposerClient通過 ISurfaceFlingerClient接口的getControlBlock()方法獲得IMemoryHeap接口指針,同時(shí)保存在 SurfaceComposerClient的成員變量mControlMemory中;
            • 繼續(xù)通過IMemoryHeap接口的getBase ()方法獲取共享內(nèi)存的首地址,轉(zhuǎn)換為SharedClient指針后保存在SurfaceComposerClient的成員變量mControl中;
            • 至此,SurfaceComposerClient的成員變量mControl和SurfaceFlinger::Client.ctrlblk指向了同一個(gè)內(nèi)存塊,該內(nèi)存塊上就是SharedClient對(duì)象。 

                2. SharedBufferStack、SharedBufferServer、SharedBufferClient

                SharedClient對(duì)象中有一個(gè)SharedBufferStack數(shù)組:

                SharedBufferStack surfaces[ NUM_LAYERS_MAX ];

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

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

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

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

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

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

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

            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共享內(nèi)存區(qū)建立了關(guān)聯(lián),并且每個(gè)Layer對(duì)應(yīng)于SharedBufferStack 數(shù)組中的一項(xiàng)。

                回到SurfaceFlinger的客戶端Surface.cpp中,Surface的構(gòu)造函數(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構(gòu)造參數(shù)mClient->mControl就是共享內(nèi)存塊中的SharedClient對(duì)象,mToken就是SharedBufferStack 數(shù)組索引值。

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



            一并參考:

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

             

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


            只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


            97久久国产综合精品女不卡| 久久久久人妻精品一区二区三区| 国产激情久久久久影院老熟女免费| 国产免费久久精品丫丫| 香蕉久久永久视频| 精品国产99久久久久久麻豆| 狠狠色婷婷久久一区二区三区| 国产99久久九九精品无码| 中文成人无码精品久久久不卡| 99久久99久久精品免费看蜜桃| 久久se这里只有精品| 久久国产精品77777| 亚洲婷婷国产精品电影人久久| 激情伊人五月天久久综合| 亚洲精品高清一二区久久| 久久99国产精品一区二区| 日日狠狠久久偷偷色综合96蜜桃 | 怡红院日本一道日本久久 | 久久无码AV一区二区三区| 99久久免费国产特黄| 亚洲熟妇无码另类久久久| 色综合久久久久综合99| 国产精品内射久久久久欢欢| 国产精品一区二区久久国产| 久久久久久久精品成人热色戒| 久久精品亚洲男人的天堂| 青青青青久久精品国产| 久久久婷婷五月亚洲97号色 | 亚洲AV无码久久精品色欲| 亚洲国产精品成人久久蜜臀| 国产免费久久久久久无码| 欧美亚洲国产精品久久蜜芽| 国产精品久久久久久搜索| 色婷婷综合久久久久中文| 亚洲精品乱码久久久久久久久久久久 | 亚洲人成电影网站久久| 久久五月精品中文字幕| 久久久久亚洲精品男人的天堂| 久久久久99精品成人片| 久久综合九色综合欧美就去吻| 久久一区二区三区免费|