Android系統(tǒng)Surface機(jī)制的SurfaceFlinger服務(wù)渲染應(yīng)用程序UI的過程分析_第1頁
Android系統(tǒng)Surface機(jī)制的SurfaceFlinger服務(wù)渲染應(yīng)用程序UI的過程分析_第2頁
Android系統(tǒng)Surface機(jī)制的SurfaceFlinger服務(wù)渲染應(yīng)用程序UI的過程分析_第3頁
Android系統(tǒng)Surface機(jī)制的SurfaceFlinger服務(wù)渲染應(yīng)用程序UI的過程分析_第4頁
Android系統(tǒng)Surface機(jī)制的SurfaceFlinger服務(wù)渲染應(yīng)用程序UI的過程分析_第5頁
已閱讀5頁,還剩45頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

Android系統(tǒng)Surface機(jī)制的

SurfaceFlinger服務(wù)渲染應(yīng)用程序UI的

過程分析在前面的一系列文章中,我們學(xué)習(xí)了Android應(yīng)用程序與SurfaceFlinger服務(wù)的關(guān)系,以及SurfaceFlinger服務(wù)的啟動過程、初始化硬件幀緩沖區(qū)的過程、線程模型。SurfaceFlinger服務(wù)所做的一切都是為了給Android應(yīng)用程序提服務(wù)的,即為Android應(yīng)用程序渲染它們的UI。在本文中,我們就詳細(xì)分析SurfaceFlinger服務(wù)渲染Android應(yīng)用程序UI的過程。從前面一文可以知道,SurfaceFlinger服務(wù)是通過它的UI渲染線程來將應(yīng)用程序的UI渲染到硬件幀緩沖區(qū)中去的,因此,接下來我們就通過分析SurfaceFlinger服務(wù)的UI渲染線程的執(zhí)行過程來分應(yīng)用程序UI的渲染過程,這個過程如圖1所示。[1■叩帀1[1■叩帀1- 從圖1就可以看出,SurfaceFlinger服務(wù)的UI渲染線程的執(zhí)行過程如下所示:1.調(diào)用SurfaceFlinger類的成員函數(shù)handleConsoleEvents來處理控制臺事件。2.調(diào)用SurfaceFlinger類的成員函數(shù)handleTransaction來處理系統(tǒng)顯示屏以及應(yīng)用程序窗口的屬性變化,例如大小、旋轉(zhuǎn)方向變化等。3.調(diào)用SurfaceFlinger類的成員函數(shù)handlePageFlip來讓各個應(yīng)用程序窗口設(shè)置它們當(dāng)前所要渲染的圖形緩沖區(qū)。4.如果SurfaceFlinger服務(wù)在編譯的時候指定了USE_COMPOSITION_BYPASS宏,并且當(dāng)前需要渲染的應(yīng)用程序窗口只有一個,那么就會調(diào)用SurfaceFlinger類的成員函數(shù)handleBypassLayer來直接將這個應(yīng)用程序窗口的圖形緩沖區(qū)渲染到硬件幀緩沖區(qū)中去,否則的話,就要調(diào)用SurfaceFlinger類的成員函數(shù)handleRepaint來合成所有的應(yīng)用程序窗口的圖形緩沖區(qū)到一個主圖形緩沖區(qū)中去。5.調(diào)用SurfaceFlinger類的成員函數(shù)postFramebuffer將前面得到的主圖形緩沖區(qū)渲染到硬件幀緩沖區(qū)中去。前面一文中,我們已經(jīng)分析過第1步的實(shí)現(xiàn)了,而通過前面這一系列文章的學(xué)習(xí),我們也已經(jīng)了解了應(yīng)用程序窗口的圖形緩沖區(qū)的創(chuàng)建過程,因此,接下來我們就在這些知識的基礎(chǔ)上來詳細(xì)分析第2步到第5的實(shí)現(xiàn),即分別分析SurfaceFlinger類的成員函數(shù)handleTransaction、handlePageFlip、handleBypassLayer和postFramebuffer的實(shí)現(xiàn)。1.handleTransactionSurfaceFlinger類的成員函數(shù)handleTransaction是用來處理系統(tǒng)顯示屏以及應(yīng)用程序窗口的屬性變化的,這個過程如圖2所示。這個過程可以分為6個步驟,接下來我們就詳細(xì)分析每一個步驟。Step1.SurfaceFlinger.handleTransaction[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片voidSurfaceFlinger::handleTransaction(uint32_ttransactionFlags){Vector<sp<LayerBase>>ditchedLayers;/**Performandcommitthetransaction*/{//scopeforthelockMutex::Autolock_l(mStateLock);constnsecs_tnow=systemTime();mDebugInTransaction=now;handleTransactionLocked(transactionFlags,ditchedLayers);mLastTransactionTime=systemTime()-now;mDebugInTransaction=0;//herethetransactionhasbeencommitted}/**Clean-upalllayersthatwentaway*(dothiswithoutthelockheld)*/constsize_tcount=ditchedLayers.size();for(size_ti=0;i<count;i++){if(ditchedLayers[i]!=0){//LOGD("ditchinglayer%p",ditchedLayers[i].get());ditchedLayers[i]->ditch();}}}這個函數(shù)定義在文件frameworks/base/services/surfaceflinger/SurfaceFlinger.cpp中。SurfaceFlinger類的成員函數(shù)handleTransaction是通過調(diào)用另外一個成員函數(shù)handleTransactionLocked來處理系統(tǒng)顯示屏以及應(yīng)用程序窗口的屬性變化的,而SurfaceFlinger類的成員函數(shù)handleTransactionLocked在處理完成系統(tǒng)顯示屏以及應(yīng)用程序窗口的屬性變化之后,會返回系統(tǒng)中那些已經(jīng)銷毀了的應(yīng)用程序窗口。從這一系列文章可以知道,在SurfaceFlinger服務(wù)這一側(cè),應(yīng)用程序窗口一般是使用一個Layer對象來描述的,又由于Layer類是從LayerBase類繼承下來的,因此,我們可以那些已經(jīng)銷毀了的應(yīng)用程序窗口保存在一個類型為spvLayerBase>的向量ditchedLayers中。SurfaceFlinger類的成員函數(shù)handleTransaction最后就調(diào)用保存在向量ditchedLayers中的每一個LayerBase對象的成員函數(shù)dtich來執(zhí)行被銷毀的應(yīng)用程序窗口的清理操作,接下來我們就繼續(xù)分析SurfaceFlinger類的成員函數(shù)handleTransactionLocked,看看它是如何處理系統(tǒng)顯示屏以及應(yīng)用程序窗口的屬性變化的。Step2.SurfaceFlinger.handleTransactionLockedSurfaceFlinger類的成員函數(shù)handleTransactionLocked定義在文件rameworks/base/services/surfaceflinger/SurfaceFlinger.cpp中,我們分三段來閱讀:[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片voidSurfaceFlinger::handleTransactionLocked(uint32_ttransactionFlags,Vector<sp<LayerBase>>&ditchedLayers){constLayerVector¤tLayers(mCurrentState.layersSortedByZ);constsize_tcount=currentLayers.size();/*Traversalofthechildren(performthetransactionforeachofthemifneeded)*/constboollayersNeedTransaction=transactionFlags&eTraversalNeeded;if(layersNeedTransaction){for(size_ti=0;i<count;i++){constsp<LayerBase>&layer=currentLayers[i];uint32_ttrFlags=layer->getTransactionFlags(eTransactionNeeded);if(!trFlags)continue;constuint32_tflags=layer->doTransaction(0);if(flags&Layer::eVisibleRegion)mVisibleRegionsDirty=true;}}這段代碼用來處理應(yīng)用程序窗口的屬性變化。參數(shù)transactionFlags最開始是從SurfaceFlinger類的成員函數(shù)threadLoop傳進(jìn)來的。從前面一文可以知道,SurfaceFlinger類的成員函數(shù)threadLoop在調(diào)用另外一個成員函數(shù)handleTransaction來處理系統(tǒng)顯示屏以及應(yīng)用程序窗口的屬性變化之前,首先會調(diào)用成員函數(shù)getTransactionFlags來檢查系統(tǒng)顯示屏或者應(yīng)用程序窗口的屬性是否發(fā)生了變化。如果系統(tǒng)顯示屏的屬性發(fā)生了變化,那么傳到這里的參數(shù)transactionFlags的eTransactionNeeded位就會等于1,而如果有應(yīng)用程序窗口的屬性發(fā)生了變化,那么傳到這里的參數(shù)transactionFlags的eTraversalNeeded位就會等于1。為了方便描述,我們假設(shè)系統(tǒng)顯示屏以及應(yīng)用程序窗口的屬性都發(fā)生了變化。SurfaceFlinger類的成員變量mCurrentState指向了一個State對象,用來描述SufaceFlinger服務(wù)的當(dāng)前狀態(tài),其中,這個State對象的成員變量layersSortedByZ是一個類型為LayerVector的向量,它里面保存了SufaceFlinger服務(wù)當(dāng)前所需要渲染的應(yīng)用程序窗口,而這些應(yīng)用程序窗口都是使用一個LayerBase對象來描述的。這段代碼首先獲得SufaceFlinger服務(wù)當(dāng)前所需要渲染的應(yīng)用程序窗口,接著再通過一個for循環(huán)來依次檢查每一個應(yīng)用程序窗口的屬性是否發(fā)生了變化。如果某一個應(yīng)用程序窗口的屬性被修改過,那么調(diào)用用來描述這個應(yīng)用程序窗口的一個LayerBase對象的成員函數(shù)getTransactionFlags得到的返回值trFlags就不會等于0,在這種情況下,這段代碼就會調(diào)用這個LayerBase對象的成員函數(shù)doTransaction來處理對應(yīng)的應(yīng)用程序窗口的屬性變化。在LayerBase類中,有一個類型為int32_t的成員變量mTransactionFlags,每當(dāng)SurfaceFlinger服務(wù)修改某一個應(yīng)用程序窗口的屬性時,都會將與其對應(yīng)的LayerBase的成員變量mTransactionFlags的相應(yīng)的位設(shè)置為1,這樣LayerBase類的成員函數(shù)getTransactionFlags就可以通過這個成員變量來判斷一個應(yīng)用程序窗口的屬性是否發(fā)生變化了。如果一個應(yīng)用程序窗口發(fā)生的屬性變化是可見區(qū)域發(fā)生了改變,那么對應(yīng)的LayerBase對象的成員函數(shù)doTransaction的返回值flags的Layer::eVisibleRegion位就會等于1。在這種情況下,這段代碼就會將SurfaceFlinger類的成員變量mVisibleRegionsDirty的值設(shè)置為true,表示后面要重新計算各個應(yīng)用程序窗口的可見區(qū)域。為了方便描述,我們假設(shè)發(fā)生了屬性變化的應(yīng)用程序窗口是一個普通類型的Surface,即用來描述它的實(shí)際是一個從LayerBase類繼承下來的Layer對象。在這種情況下,前面實(shí)際上調(diào)用了Layer類的成員函數(shù)doTransaction來處理一個應(yīng)用程序窗口的屬性變化。在接下來的Step3中,我們再詳細(xì)分析Layer類的成員函數(shù)doTransaction的實(shí)現(xiàn),現(xiàn)在我們接著往下閱讀SurfaceFlinger類的成員函數(shù)handleTransactionLocked的代碼:[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片/**Performourowntransactionifneeded*/if(transactionFlags&eTransactionNeeded){if(mCurrentState.orientation!=mDrawingState.orientation){//theorientationhaschanged,recomputeallvisibleregions//andinvalidateeverything.constintdpy=0;constintorientation=mCurrentState.orientation;constuint32_ttype=mCurrentState.orientationType;GraphicPlane&plane(graphicPlane(dpy));plane.setOrientation(orientation);//updatethesharedcontrolblockconstDisplayHardware&hw(plane.displayHardware());volatiledisplay_cblk_t*dcblk=mServerCblk->displays+dpy;dcblk->orientation=orientation;dcblk->w=plane.getWidth();dcblk->h=plane.getHeight();mVisibleRegionsDirty=true;mDirtyRegion.set(hw.bounds());}if(mCurrentState.freezeDisplay!=mDrawingState.freezeDisplay){//freezingorunfreezingthedisplay->triggeranimationifneededmFreezeDisplay=mCurrentState.freezeDisplay;if(mFreezeDisplay)mFreezeDisplayTime=0;}if(currentLayers.size()>mDrawingState.layersSortedByZ.size()){//layershavebeenaddedmVisibleRegionsDirty=true;}//somelayersmighthavebeenremoved,so//weneedtoupdatetheregionsthey'reexposing.if(mLayersRemoved){mLayersRemoved=false;mVisibleRegionsDirty=true;constLayerVector&previousLayers(mDrawingState.layersSortedByZ);constsize_tcount=previousLayers.size();for(size_ti=0;i<count;i++){constsp<LayerBase>&layer(previousLayers[i]);if(currentLayers.indexOf(layer)<0){//thislayerisnotvisibleanymoreditchedLayers.add(layer);mDirtyRegionRemovedLayer.orSelf(layer->visibleRegionScreen);}}}}這段代碼用來處理系統(tǒng)顯示屏的屬性變化。在分析這段代碼之前,我們首先了解SurfaceFlinger類的另外一個成員變量mDrawingState的含義。SurfaceFlinger類的成員變量mDrawingState與前面所介紹的成員變量mCurrentState類似,它的類型也為State,不過它是用來描述SufaceFlinger服務(wù)的上一次渲染狀態(tài)的。通過這兩個成員變量的比較,我們就可以知道系統(tǒng)顯示屏的哪一個屬性發(fā)生了變化。前面提到,當(dāng)系統(tǒng)顯示屏的屬性發(fā)生了變化,那么參數(shù) transactionFlags的eTransactionNeeded位就會等于1,在這種情況,這段代碼就需要完成四件事情。第一件事情是判斷系統(tǒng)顯示屏的旋轉(zhuǎn)方向是否發(fā)生變化。State類的成員變量orientation用來描述顯示屏的方向,因此,當(dāng)SurfaceFlinger類的成員變量mCurrentState所描述的一個State對象的成員變量orientation的值不等于SurfaceFlinger類的成員變量mDrawingState所描述的一個State對象的成員變量orientation的值時,就說明系統(tǒng)顯示屏的旋轉(zhuǎn)方向發(fā)生了變化。在這種情況下,我們就需要將系統(tǒng)顯示屏的旋轉(zhuǎn)方向設(shè)置為SurfaceFlinger類的成員變量mCurrentState所描述的一個State對象的成員變量orientation的值,這是通過調(diào)用編號為0的一個GraphicPlane對象的成員函數(shù)setOrientation來實(shí)現(xiàn)的。SurfaceFlinger服務(wù)的UI渲染線程在初始化的過程中,除了會初始化硬件幀緩沖區(qū)之外,還會創(chuàng)建一個類型為surface_flinger_cblk_t的對象,用來描述系統(tǒng)顯示屏的信息,例如大小和旋轉(zhuǎn)方向等,以便其它進(jìn)程可以通過這個surface_flinger_cblk_t對象來獲得系統(tǒng)顯示屏的信息。這個surface_flinger_cblk_t對象就保存在SurfaceFlinger類的成員變量mServerCblk中。因此,當(dāng)系統(tǒng)顯示屏的旋轉(zhuǎn)方向發(fā)生了變化時,我們還需要將變化后的旋轉(zhuǎn)方向保存在SurfaceFlinger類的成員變量mServerCblk所描述的一個surface_flinger_cblk_t對象中。由于系統(tǒng)顯示屏的旋轉(zhuǎn)方向變化一般意味著寬度和高度也會發(fā)生變化,因此,我們還需要將旋轉(zhuǎn)發(fā)生變化后得到的系統(tǒng)顯示屏的寬度和高度值保存在SurfaceFlinger類的成員變量mServerCblk所描述的一個surface_flinger_cblk_t對象中。系統(tǒng)顯示屏的旋轉(zhuǎn)方向同時也意味著我們需要重新計算各個應(yīng)用程序窗口的可見區(qū)域以及重新繪制整個顯示屏,因此,在這種情況下,我們還需要將SurfaceFlinger類的成員變量mVisibleRegionsDirty的值設(shè)置為true,以及將SurfaceFlinger類的成員變量mDirtyRegion的大小設(shè)置為整個顯示屏的大小,即將系統(tǒng)UI的臟區(qū)域設(shè)置為整個顯示屏的大小。第二件事情是判斷系統(tǒng)顯示屏的凍結(jié)狀態(tài)是否發(fā)生變化。State類的成員變量freezeDisplay用來描述顯示屏的凍結(jié)狀態(tài),因此,當(dāng)SurfaceFlinger類的成員變量mCurrentState所描述的一個State對象的成員變量freezeDisplay的值不等于SurfaceFlinger類的成員變量mDrawingState所描述的一個State對象的成員變量freezeDisplay的值時,就說明系統(tǒng)顯示屏的凍結(jié)狀態(tài)發(fā)生了變化。在這種情況下,我們就需要將SurfaceFlinger類的成員變量mFreezeDisplay的值設(shè)置為SurfaceFlinger類的成員變量mCurrentState所描述的一個State對象的成員變量freezeDisplay的值。如果顯示屏的是由解凍狀態(tài)變化為凍結(jié)狀態(tài)的,那么還需要將顯示屏的凍結(jié)時間設(shè)置為0,即將SurfaceFlinger類的成員變量mFreezeDisplayTime的值設(shè)置為0,以便可以將顯示屏進(jìn)入到凍結(jié)狀態(tài)的最長時間設(shè)置為一個默認(rèn)值,這一點(diǎn)可以參考前面一文。第三件事情是判斷是否新增了應(yīng)用程序窗口。State類的成員變量layersSortedByZ是一個類型LayerVector的向量,里面保存的是SurfaceFlinger服務(wù)在某一個狀態(tài)下所擁有的應(yīng)用程序窗口,因此,當(dāng)SurfaceFlinger類的成員變量mCurrentState所描述的一個State對象的成員變量layersSortedByZ所指向的一個向量的大小值大于SurfaceFlinger類的成員變量mDrawingState所描述的一個State對象的成員變量layersSortedByZ所指向的一個向量的大小值時,就說明系統(tǒng)新增了應(yīng)用程序窗口。在這種情況下,我們就需要將SurfaceFlinger類的成員變量mVisibleRegionsDirty的值設(shè)置為true,以表示我們需要重新計算各個應(yīng)用程序窗口的可見區(qū)域。第四件事情是判斷是否移除了某些應(yīng)用程序窗口。SurfaceFlinger類的成員變量mLayersRemoved用來描述是否有應(yīng)用程序窗口被移除了。如果有有應(yīng)用程序窗口被移除的話,那么這個成員變量的值就會等于true。在這種情況下,我們就需要是哪些應(yīng)用程序窗口被移除了。計算的方法很簡單,如果一個應(yīng)用程序窗口存在于SurfaceFlinger類的成員變量mDrawingState所描述的一個State對象的成員變量layersSortedByZ所指向的一個向量中,但是不存在于SurfaceFlinger類的成員變量mCurrentState所描述的一個State對象的成員變量layersSortedByZ所指向的一個向量中,那么就說明這個應(yīng)用程序窗口被移除了,因此,就需要將它保存輸出參數(shù)ditchedLayers所描述的一個向量中,以便可以返回給上一步來處理。SurfaceFlinger類的成員變量mDirtyRegionRemovedLayer用來描述那些被移除了的應(yīng)用程序窗口所占用的區(qū)域,因此,每當(dāng)我們移除一個應(yīng)用程序窗口的時候,都需要將它所占用的區(qū)域增加到SurfaceFlinger類的成員變量mDirtyRegionRemovedLayer所描述的一個區(qū)域去。當(dāng)處理完成那些被移除的應(yīng)用程序窗口之后,我們就需要將SurfaceFlinger類的成員變量mLayersRemoved的值設(shè)置為false,并且將SurfaceFlinger類的成員變量mVisibleRegionsDirty的值設(shè)置為true,以表示我們需要重新計算現(xiàn)存的各個應(yīng)用程序窗口的可見區(qū)域。處理完成系統(tǒng)顯示屏的屬性變化之后,我們接著向下閱讀SurfaceFlinger類的成員函數(shù)handleTransactionLocked的最后一行代碼:[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片commitTransaction();這段代碼只有一行,即調(diào)用SurfaceFlinger類的成員函數(shù)commitTransaction來告訴SurfaceFlinger服務(wù),系統(tǒng)顯示屏以及各個應(yīng)用程序窗口的屬性變化已經(jīng)處理完畢,這時候SurfaceFlinger服務(wù)就可以切換狀態(tài)了。在后面的Step6中,我們再詳細(xì)分析SurfaceFlinger類的成員函數(shù)commitTransaction的實(shí)現(xiàn)。接下來,我們就繼續(xù)分析Layer類的成員函數(shù)doTransaction的實(shí)現(xiàn),以便可以了解應(yīng)用程序窗口的屬性變化的處理過程。Step3.Layer.doTransaction[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片uint32_tLayer::doTransaction(uint32_tflags){constLayer::State&front(drawingState());constLayer::State&temp(currentState());constboolsizeChanged=(front.requested_w!=temp.requested_w)||(front.requested_h!=temp.requested_h);if(sizeChanged){if(!isFixedSize()){//we'rebeingresizedandthereisafreezedisplayrequest,//acquireafreezelock,sothatthescreenstaysput//untilwe'veredrawnatthenewsize;thisistoavoid//glitchesuponorientationchanges.if(mFlinger->hasFreezeRequest()){//ifthesurfaceishidden,don'ttrytoacquirethe//freezelock,sincehiddensurfacesmayneverredrawif(!(front.flags&ISurfaceComposer::eLayerHidden)){

mFreezeLock=mFlinger->getFreezeLock();}}//thiswillmakesureLayerBase::doTransactiondoesn'tupdate//thedrawingstate'ssizeLayer::State&editDraw(mDrawingState);editDraw.requested_w=temp.requested_w;editDraw.requested_h=temp.requested_h;//recordthenewsize,formthispointon,whentheclientrequest//abuffer,it'llgetthenewsize.setBufferSize(temp.requested_w,temp.requested_h);ClientRef::AccesssharedClient(mUserClientRef);SharedBufferServer*lcblk(sharedClient.get());if(lcblk){//allbuffersneedreallocationlcblk->reallocateAll();}}else{//recordthenewsizesetBufferSize(temp.requested_w,temp.requested_h);}}if(temp.sequence!=front.sequence){if(temp.flags&ISurfaceComposer::eLayerHidden||temp.alpha==0){//thissurfaceisnowhidden,soitshouldn'tholdafreezelock//(itmayneverredraw,whichisfineifitishidden)mFreezeLock.clear();}}returnLayerBase::doTransaction(flags);}這個函數(shù)定義在文件frameworks/base/services/surfaceflinger/Layer.cpp中。和SurfaceFlinger服務(wù)類似,每一個應(yīng)用程序窗口在內(nèi)部也分別使用兩個類型為State的成員變量mDrawingState和mCurrentState來描述上一次的渲染狀態(tài)和下一次的渲染狀態(tài)。這兩個成員變量是從LayerBase類繼承下來的,用來描述應(yīng)用程序窗口的Layer類可以分別通過從父類LayerBase繼承下來的成員函數(shù)drawingState和currentState來訪問它們。注意,這里所說的State類是定義在LayerBase類內(nèi)部的,而SurfaceFlinger服務(wù)使用的State類是定義在SurfaceFlinger類內(nèi)部的,它們是不一樣的。Layer類的成員函數(shù)doTransaction首先調(diào)用從父類LayerBase繼承下來的成員函數(shù)drawingState和currentstate來獲得當(dāng)前正在處理的應(yīng)用程序窗口的上一次的渲染狀態(tài)和下一次的渲染狀態(tài),并且分別保存在兩個類型為State的變量front和temp中。State類的成員變量requested_w和requested_h分別用來描述應(yīng)用程序窗口的寬度和高度,因此,當(dāng)State變量front的成員變量requested_w和requested」不等于State變量temp的成員變量requested_w和requested」時,我們就會得到變量sizeChanged的值等于true,表示當(dāng)前正在處理的應(yīng)用程序窗口的大小發(fā)生了變化。在分析Layer類的成員函數(shù)doTransaction處理應(yīng)用程序窗口的大小變化時,我們先介紹Layer類的成員變量mFixedSize的含義。Layer類的成員變量mFixedSize是一個布爾變量,它的值可以通過Layer類的成員函數(shù)isFixedSize來獲得。從前面 一文可以知道,當(dāng)Android應(yīng)用程序請求SurfaceFlinger服務(wù)分配一塊圖形緩沖區(qū)時,Layer類的成員函數(shù)requestBuffer就會被調(diào)用。這時候Android應(yīng)用程序會傳遞兩個參數(shù)reqWidth和reqHeight過來,表示請求分配的圖形緩沖區(qū)的寬度和高度。這兩個參數(shù)是可以同時等于0的,表示使用默認(rèn)的寬度和高度值來創(chuàng)建所請求的圖形緩沖區(qū)。這兩個默認(rèn)的寬度和高度值即等于當(dāng)前所處理的應(yīng)用程序窗口的寬度和高度值,而后者的寬度和高度值是在其創(chuàng)建的時候指定的,這一點(diǎn)可以參考一文。Layer類的成員函數(shù)requestBuffer的參數(shù)reqWidth和reqHeight的值等于0意味著什么呢?從前面 一文還可以知道‘Android應(yīng)用程序在請求SurfaceFlinger服務(wù)分配一塊圖形緩沖區(qū)之前,會通過在Surface類內(nèi)部定義的BufferInfo類的成員函數(shù)validateBuffer來檢查當(dāng)前所處理的應(yīng)用程序窗口的大小是否發(fā)生了變化。如果發(fā)生了變化,那么Android應(yīng)用程序就會忽略掉緩存自己一側(cè)的圖形緩沖區(qū),而去SurfaceFlinger服務(wù)請求新的圖形緩沖區(qū),因?yàn)槟切┚彺娴膱D形緩沖區(qū)由于與它們所關(guān)聯(lián)的應(yīng)用程序窗口大小發(fā)生了變化而變?yōu)闊o效了。但是有一種特殊情況,在Android應(yīng)用程序這一側(cè),用來描述應(yīng)用程序窗口的Surface類可以不維護(hù)應(yīng)用程序窗口的大小值。在這種情況下,Surface類就會將與它所關(guān)聯(lián)的應(yīng)用程序窗口的大小值設(shè)置為0,這意味著Android應(yīng)用程序每次為這個應(yīng)用程序窗口向SurfaceFlinger服務(wù)請求分配圖形緩沖區(qū)之前,都認(rèn)為這個應(yīng)用程序窗口的大小值沒有發(fā)生變化,同時傳遞給Layer類的成員函數(shù)requestBuffer的參數(shù)reqWidth和reqHeight的值會等于0。事實(shí)上,一個應(yīng)用程序窗口的大小是隨時都可以發(fā)生變化的,比如,我們可以通過調(diào)用用來在Android應(yīng)用程序和SurfaceFlinger服務(wù)建立連接的一個類型為Client的Binder對象的成員函數(shù)setState來改變一個應(yīng)用程序窗口的大小,而一旦一個應(yīng)用程序窗口的大小發(fā)生了變化,我們正在分析Layer類的成員函數(shù)doTransaction就會被調(diào)用。從上面的分析就可以得出一個結(jié)論,Layer類的成員函數(shù)doTransaction在處理應(yīng)用程序窗口大小變化時,需要考慮Android應(yīng)用程序每次在為該應(yīng)用程序窗口向SurfaceFlinger服務(wù)請求分配圖形緩沖區(qū)之前,是否有能力去判斷之前為該應(yīng)用程序窗口緩存的圖形緩沖區(qū)的有效性。如果沒有的話,那么Layer類的成員函數(shù)doTransaction就需要將為該應(yīng)用程序窗口緩存的圖形緩沖區(qū)設(shè)置為無效,以便以后Android應(yīng)用程序可以請求SurfaceFlinger服務(wù)分配新的、大小正確的圖形緩沖區(qū)。從前面的分析還可以知道,當(dāng)Android應(yīng)用程序沒有能力去判斷之前為一個應(yīng)用程序窗口所緩存的圖形緩沖區(qū)的有效性時,那么之前在請求分配這些圖形緩沖區(qū)時,傳遞給Layer類的成員函數(shù)requestBuffer的參數(shù)reqWidth和reqHeight的值就會等于0,這時候Layer類的成員函數(shù)requestBuffer就會將Layer類的成員變量mFixedSize的值設(shè)置為false。接下來,我們就分別根據(jù)Layer類的成員變量mFixedSize是等于true還是false來分析Layer類的成員函數(shù)doTransaction處理一個應(yīng)用程序窗口大小發(fā)生變化的過程。當(dāng)Layer類的成員變量mFixedSize的值等于true時,Layer類的成員函數(shù)doTransaction的處理很簡單,它只是調(diào)用另外一個成員函數(shù)setBufferSize來將新的應(yīng)用程序窗口大小記錄下來,即保存在Layer類的成員變量mWidth和mHeight中。當(dāng)Layer類的成員變量mFixedSize的值等于false時,由于Android應(yīng)用程序沒有能力去判斷之前為一個應(yīng)用程序窗口所緩存的圖形緩沖區(qū)的有效性,因此,Layer類的成員函數(shù)doTransaction除了會調(diào)用外一個成員函數(shù)setBufferSize來將新的應(yīng)用程序窗口大小記錄下來之外,還會通過一個SharedBufferServer對象的成員函數(shù)reallocateAll來將為當(dāng)前正在處理的應(yīng)用程序窗口所緩存的圖形緩沖區(qū)設(shè)置為無效。在前面一文中,我們已經(jīng)分析過SharedBufferServer類的作用了,它是用來維護(hù)Android應(yīng)用程序與SurfaceFlinger服務(wù)之間的共享UI元數(shù)據(jù)的,通過它可以將對應(yīng)的圖形緩沖區(qū)設(shè)置為無效。當(dāng)Layer類的成員變量mFixedSize的值等于false時,Layer類的成員函數(shù)doTransaction還會提前將成員變量mCurrentState所描述的一個State對象的成員變量requested_w和requested_h的值保存到成員變量mDrawingState所描述的一個State對象的成員變量requested_w和requested_h中去,這是為了避免后面調(diào)用父類LayerBase的成員函數(shù)doTransaction時,會返回一個Layer::eVisibleRegion位不等于0的標(biāo)志值給前面的Step2,而這將會導(dǎo)致SurfaceFlinger服務(wù)馬上重新計算各個應(yīng)用程序窗口的可見區(qū)域?,F(xiàn)在不返回一個Layer::eVisibleRegion位不等于0的標(biāo)志值給前面的Step2,就會等到下次渲染當(dāng)前正在處理的應(yīng)用程序窗口時再重新計算各個應(yīng)用程序窗口的可見區(qū)域。此外,當(dāng)Layer類的成員變量mFixedSize的值等于false時,Layer類的成員函數(shù)doTransaction還會檢查系統(tǒng)顯示屏是否正處于凍結(jié)的狀態(tài),這是通過調(diào)用Layer類的成員變量mFlinger所指向的SurfaceFlinger服務(wù)的成員函數(shù)hasFreezeRequest來實(shí)現(xiàn)的。如果系統(tǒng)顯示屏處于凍結(jié)的狀態(tài)中,并且當(dāng)前正在處理的應(yīng)用程序窗口處于可見狀態(tài),即變量front所描述的State對象的成員變量flags的ISurfaceComposer::eLayerHidden位等于0,那么Layer類的成員函數(shù)doTransaction還會請求獲得一個用來凍結(jié)系統(tǒng)顯示屏的類型為FreezeLock的鎖,并且將這個鎖保存在Layer類的成員變量mFreezeLock中。這樣就可以等到下次渲染當(dāng)前正在處理的應(yīng)用程序窗口時,再來刷新系統(tǒng)的UI。State類的另外一個成員變量sequence用來描述一個應(yīng)用程序窗口的其它屬性是否發(fā)生過變化,例如,X、Y和Z軸位置、透明度等除了大小之外的屬性。每當(dāng)這些屬性發(fā)生了變化,那么State類的成員變量sequence的值就會比原來增加1。Layer類的成員函數(shù)doTransaction再接下來就通過比較變量temp和front所描述的State對象的成員變量sequence的值是否相等來判斷當(dāng)前正在處理的應(yīng)用程序窗口的其它屬性是否發(fā)生變化。如果發(fā)生過變化,并且當(dāng)前正在處理的應(yīng)用程序窗口處于不可見狀態(tài)或者處于完全透明的狀態(tài),那么Layer類的成員函數(shù)doTransaction就會釋放之前所持有的用來凍結(jié)系統(tǒng)顯示屏的一個類型為FreezeLock的鎖,這是通過調(diào)用Layer類的成員變量mFreezeLock所指向的一個FreezeLock對象的成員函數(shù)clear來實(shí)現(xiàn)的,這樣就可以避免阻止SurfaceFlinger服務(wù)更新系統(tǒng)UI。最后,Layer類的成員函數(shù)doTransaction調(diào)用父類LayerBase的成員函數(shù)doTransaction來繼續(xù)處理應(yīng)用程序窗口的屬性變化。Step4.LayerBase.doTransaction[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片uint32_tLayerBase::doTransaction(uint32_tflags){constLayer::State&front(drawingState());constLayer::State&temp(currentState());if((front.requested_w!=temp.requested_w)||(front.requested_h!=temp.requested_h)){//resizethelayer,setthephysicalsizetotherequestedsizeLayer::State&editTemp(currentState());editTemp.w=temp.requested_w;editTemp.h=temp.requested_h;}if((front.w!=temp.w)||(front.h!=temp.h)){//invalidateandrecomputethevisibleregionsifneededflags|=Layer::eVisibleRegion;}if(temp.sequence!=front.sequence){//invalidateandrecomputethevisibleregionsifneededflags|=eVisibleRegion;this->contentDirty=true;//wemayuselinearfiltering,ifthematrixscalesusconstuint8_ttype=temp.transform.getType();mNeedsFiltering=(!temp.transform.preserveRects()||(type>=Transform::SCALE));}//CommitthetransactioncommitTransaction();returnflags;}這個函數(shù)定義在文件frameworks/base/services/surfaceflinger/LayerBase.cpp中。與前面的Step3一樣,LayerBase類的成員函數(shù)doTransaction首先通過成員函數(shù)drawingState和currentState來獲得用來描述當(dāng)前正在處理的應(yīng)用程序窗口的當(dāng)前渲染狀態(tài)的一個State對象front和下一次渲染狀態(tài)的一個State對象temp,接下來就可以通過這兩個State對象的成員變量requested_w和requested_h來判斷當(dāng)前正在處理的應(yīng)用程序窗口的大小是否發(fā)生了變化。如果發(fā)生了變化,那么就將新的應(yīng)用程序窗口大小值保存在用來描述下一次渲染狀態(tài)的State對象editTemp的成員變量w和h中。State類的成員變量requested_w、requested」和w、h的區(qū)別在于,前兩者用來描述應(yīng)用程序窗口的大小,后兩者雖然也是用來描述應(yīng)用程序窗口的大小,不過它們的作用是用來判斷是否需要重新計算系統(tǒng)中的各個應(yīng)用程序窗口的可見區(qū)域的。一旦用來描述應(yīng)用程序窗口的當(dāng)前渲染狀態(tài)的State對象front和下一次渲染狀態(tài)的State對象temp的成員變量w和h不相等,那么就說明需要系統(tǒng)中的各個應(yīng)用程序窗口的可見區(qū)域,這是通過將將返回值flags的Layer::eVisibleRegion位設(shè)置為1來實(shí)現(xiàn)的。LayerBase類的成員函數(shù)doTransaction接下來還會繼續(xù)判斷State對象front和temp的成員變量sequence的值是否相等。如果不相等,那么就說明當(dāng)前正在處理的應(yīng)用程序窗口的其它屬性,例如位置和透明度等發(fā)生了變化。在這種情況下,SurfaceFlinger服務(wù)也是需要重新計算系統(tǒng)中的各個應(yīng)用程序窗口的可見區(qū)域的。因此,這時候LayerBase類的成員函數(shù)doTransaction就會將它的返回值flags的Layer::eVisibleRegion位設(shè)置為1,并且將Layer類的成員變量contentDirty的值設(shè)置為true,表示當(dāng)前正在處理的應(yīng)用程序窗口的內(nèi)容是臟的,需要重新渲染。LayerBase類的成員函數(shù)doTransaction最后還會繼續(xù)調(diào)用另外一個成員函數(shù)commitTransaction來結(jié)束對當(dāng)前正在處理的應(yīng)用程序窗口的屬性變化處理,以及將返回值flags返回給前面的Step2,即SurfaceFlinger類的成員函數(shù)handleTransactionLocked。SurfaceFlinger類的成員函數(shù)handleTransactionLocked一旦發(fā)現(xiàn)這個返回值的Layer::eVisibleRegion位的值為1,那么就會將SurfaceFlinger類的成員變量mVisibleRegionsDirty的值設(shè)置為true,以便接下來可以重新計算系統(tǒng)中的各個應(yīng)用程序窗口的可見區(qū)域。接下來,我們就繼續(xù)分析LayerBase類的成員函數(shù)commitTransaction的實(shí)現(xiàn)。Step5.LayerBmitTransaction[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片voidLayerBase::commitTransaction(){mDrawingState=mCurrentState;}這個函數(shù)定義在文件frameworks/base/services/surfaceflinger/LayerBase.cpp中。由于此時當(dāng)前正在處理的應(yīng)用程序窗口的屬性變化已經(jīng)處理完成了,因此,LayerBase類的成員函數(shù)commitTransaction就將用來描述下一次渲染狀態(tài)的成員變量mCurrentState所描述的一個State對象保存在另外一個用來描述當(dāng)前渲染狀態(tài)的成員變量mDrawingState中去。這一步執(zhí)行完成之后,返回到前面的Step2中,即SurfaceFlinger類的成員函數(shù)handleTransactionLocked中,這時候系統(tǒng)顯示屏的屬性變化以及各個應(yīng)用程序的屬性變化就都已經(jīng)處理完成了,SurfaceFlinger類的成員函數(shù)handleTransactionLocked最后就會調(diào)用另外一個成員函數(shù)commitTransaction來結(jié)束整個屬性變化處理過程。Step6.SurfaceFmitTransaction[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片voidSurfaceFlinger::commitTransaction(){mDrawingState=mCurrentState;mResizeTransationPending=false;mTransactionCV.broadcast();}這個函數(shù)定義在文件frameworks/base/services/surfaceflinger/SurfaceFlinger.cpp中。前面提到,SurfaceFlinger類的成員變量mDrawingState用來描述SufaceFlinger服務(wù)的當(dāng)前狀態(tài),而成員變量mCurrentState用來描述SufaceFlinger服務(wù)的下一個狀態(tài),由于這時候SufaceFlinger服務(wù)的狀態(tài)變化已經(jīng)處理完成了,因此,SurfaceFlinger類的commitTransaction就將成員變量mCurrentState所指向的一個State對象保存在成員變量mDrawingState中,接著又將成員變量mResizeTransationPending的值設(shè)置為false,表示SufaceFlinger服務(wù)已經(jīng)處理過系統(tǒng)顯示屏或者應(yīng)用程序窗口的大小變化了,最后調(diào)用成員變量mTransactionCV所描述的一個條件變量的成員函數(shù)broadcast來通知其它線程,例如Binder線程,SufaceFlinger服務(wù)已經(jīng)處理完成一次屬性變化了。至此,我們就分析完成系統(tǒng)顯示屏以及應(yīng)用程序窗口的屬性變化的處理過程,接下來我們繼續(xù)分析各個應(yīng)用程序窗口是如何設(shè)置它們當(dāng)前所要渲染的圖形緩沖區(qū)的,即SurfaceFlinger類的成員函數(shù)handlePageFlip的實(shí)現(xiàn)。2.handlePageFlip

SurfaceFlinger類的成員函數(shù)handlePageFlip是用來讓各個應(yīng)用程序窗口設(shè)置它們當(dāng)前所要渲染的圖形緩沖區(qū)的,在這個過程中,SurfaceFlinger服務(wù)還會計算各個應(yīng)用程序窗口的可見區(qū)域,如圖3所示。圖M應(yīng)用程序窗口設(shè)置當(dāng)前所要痘染的閣形緩沖區(qū)的過程這個過程可以分為7個步驟,接下來我們就詳細(xì)分析每一個步驟。Step1.SurfaceFlinger.handlePageFlip[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片voidSurfaceFlinger::handlePageFlip(){boolvisibleRegions=mVisibleRegionsDirty;LayerVector¤tLayers=const_cast<LayerVector&>(mDrawingState.layersSortedByZ);visibleRegions|=lockPageFlip(currentLayers);constDisplayHardware&hw=graphicPlane(0).displayHardware();constRegionscreenRegion(hw.bounds());if(visibleRegions){RegionopaqueRegion;computeVisibleRegions(currentLayers,mDirtyRegion,opaqueRegion);/**rebuildthevisiblelayerlist*/mVisibleLayersSortedByZ.clear();constLayerVector¤tLayers(mDrawingState.layersSortedByZ);size_tcount=currentLayers.size();mVisibleLayersSortedByZ.setCapacity(count);for(size_ti=0;i<count;i++){if(!currentLayers[i]->visibleRegionScreen.isEmpty())mVisibleLayersSortedByZ.add(currentLayers[i]);}#ifdefUSE_COMPOSITION_BYPASSsp<LayerBase>bypassLayer;constsize_tnumVisibleLayers=mVisibleLayersSortedByZ.size();if(numVisibleLayers==1){constsp<LayerBase>&candidate(mVisibleLayersSortedByZ[0]);constRegion&visibleRegion(candidate->visibleRegionScreen);constRegionreminder(screenRegion.subtract(visibleRegion));if(reminder.isEmpty()){//fullscreencandidate!bypassLayer=candidate;}}setBypassLayer(bypassLayer);#endifmWormholeRegion=screenRegion.subtract(opaqueRegion);mVisibleRegionsDirty=false;}unlockPageFlip(currentLayers);mDirtyRegion.andSelf(screenRegion);}這個函數(shù)定義在文件frameworks/base/services/surfaceflinger/SurfaceFlinger.cpp中。函數(shù)首先將SurfaceFlinger類的成員變量mVisibleRegionsDirty的值保存在變量visibleRegions中。從前面第1部分的內(nèi)容可以知道,當(dāng)SurfaceFlinger服務(wù)在處理系統(tǒng)顯示屏以及各個應(yīng)用程序窗口的屬性變化時,如果發(fā)現(xiàn)需要重新計算各個應(yīng)用程序窗口的可見區(qū)域,那么就會將SurfaceFlinger類的成員變量mVisibleRegionsDirty的值設(shè)置為true。函數(shù)接下來通過SurfaceFlinger類的成員變量mDrawingState所描述的一個State對象的成員變量layersSortedByZ來獲得系統(tǒng)當(dāng)前所有的應(yīng)用程序窗口,并且保存在一個類型為LayerVector的向量currentLayers中。有了系統(tǒng)當(dāng)前所有的應(yīng)用程序窗口之后,就可以通過調(diào)用SurfaceFlinger類的成員函數(shù)lockPageFlip來讓它們設(shè)置自己當(dāng)前所要渲染的圖形緩沖區(qū)。在后面的Step2中,我們再詳細(xì)分析SurfaceFlinger類的成員函數(shù)lockPageFlip的實(shí)現(xiàn)。系統(tǒng)中的各個應(yīng)用程序窗口在設(shè)置自己當(dāng)前所要渲染的圖形緩沖區(qū)的過程中,有可能會改變自己的大小。在這種情況下,它們就會通過SurfaceFlinger類的成員函數(shù)lockPageFlip來返回一個true值來給SurfaceFlinger類的成員函數(shù)handlePageFlip,這時候得到的變量visibleRegions的值就會等于true,表示需要重新計算各個應(yīng)用程序窗口的可見區(qū)域。綜合上述情況,無論變量visibleRegions的值是由于什么原因等于true,都說明SurfaceFlinger服務(wù)需要重新計算各個應(yīng)用程序窗口的可見區(qū)域,這個計算的工作是通過調(diào)用SurfaceFlinger類的另外一個成員函數(shù)computeVisibleRegions來完成的。在后面的Step5中,我們再詳細(xì)分析SurfaceFlinger類的成員函數(shù)computeVisibleRegions的實(shí)現(xiàn)。SurfaceFlinger類的成員函數(shù)computeVisibleRegions在計算完成各個應(yīng)用程序窗口的可見區(qū)域之后,會得到一個全局不透明區(qū)域,保存在輸出參數(shù)opaqueRegion中。這個全局不透明區(qū)域就是接下來需要渲染的,一般情況下,它的大小就應(yīng)該等于顯示屏的大小,即變量screenRegion所描述的區(qū)域。在異常情況下,可能會導(dǎo)致顯示屏區(qū)域screenRegion大于全局不透明區(qū)域opaqueRegion,這時候前者減去后者就可以得到一些稱為“蟲洞”的區(qū)域,它們保存在SurfaceFlinger類的成員變量mWormholeRegion中。由于這些蟲洞區(qū)域不會被各個應(yīng)用程序窗口覆蓋,因此,SurfaceFlinger服務(wù)需要對它們進(jìn)行特殊處理,即以一種特殊的方式來渲染它們。在后面的第4部分內(nèi)容中,我們就會看到SurfaceFlinger服務(wù)是通過調(diào)用SurfaceFlinger類的成員函數(shù)drawWormhole來渲染這些蟲洞的。SurfaceFlinger類的成員函數(shù)computeVisibleRegions在計算完成各個應(yīng)用程序窗口的可見區(qū)域之后,各個應(yīng)用程序窗口的可見區(qū)域就會保存在用來描述它們的一個LayerBase對象的成員變量visibleRegionScreen中,因此,SurfaceFlinger類的成員函數(shù)handlePageFlip就會通過這個成員變量來排除掉那些可見區(qū)域?yàn)榭盏膽?yīng)用程序窗口,并且將所有可見區(qū)域不為空的應(yīng)用程序窗口按照它們的Z軸大小保存在SurfaceFlinger類的成員變量mVisibleLayersSortedByZ所描述的一個向量中。經(jīng)過前面的操作之后,SurfaceFlinger類的成員函數(shù)handlePageFlip就可以將成員變量mVisibleRegionsDirty的值設(shè)置為false了,因?yàn)檫@時候系統(tǒng)中各個應(yīng)用程序窗口的可見區(qū)域都已經(jīng)重新計算過了。SurfaceFlinger類的成員函數(shù)handlePageFlip最后就調(diào)用另外一個成員函數(shù)unlockPageFlip來讓各個應(yīng)用程序窗口執(zhí)行一些善后的工作,例如,讓各個應(yīng)用程序窗口檢查自己的可見區(qū)域是否等于空,如果等于空的話,那么就需要將它們之前所獲得的用來凍結(jié)顯示屏的鎖釋放掉,以避免阻止SurfaceFlinger服務(wù)渲染系統(tǒng)UI。在后面的Step6中,我們再詳細(xì)分析SurfaceFlinger類的成員函數(shù)unlockPageFlip的實(shí)現(xiàn)。SurfaceFlinger類的成員函數(shù)handlePageFlip最后還需要做的另外一件事情是將設(shè)置系統(tǒng)的臟區(qū)域,這個臟區(qū)域保存在SurfaceFlinger類的成員變量mDirtyRegion中,它同樣是作為一個輸出參數(shù)來傳遞給SurfaceFlinger類的成員函數(shù)computeVisibleRegions的,以便后者在計算各個應(yīng)用程序窗口的可見區(qū)域時,可以將獲得的系統(tǒng)臟區(qū)域保存在它里面。我們同樣是在后面的Step5中分析SurfaceFlinger類的成員函數(shù)computeVisibleRegions的實(shí)現(xiàn)時,再看看系統(tǒng)的臟區(qū)域是如何計算的。有一種特殊情況,即SurfaceFlinger類的成員函數(shù)handlePageFlip在重新計算完成各個應(yīng)用程序窗口的可見區(qū)域后,如果滿足以下三個條件:SurfaceFlinger服務(wù)在編譯時指定了宏USE_COMPOSITION_BYPASS;當(dāng)前要渲染的應(yīng)用程序窗口只有一個,即SurfaceFlinger類的成員變量mVisibleLayersSortedByZ所描述的一個向量的大小等于1;當(dāng)前要渲染的一個唯一的應(yīng)用程序窗口的可見區(qū)域的大小不為空。那么SurfaceFlinger服務(wù)就會直接將這個唯一需要渲染的應(yīng)用程序窗口的圖形緩沖區(qū)渲染到硬件幀緩沖區(qū)中去,以跳過后面的合成各個應(yīng)用程序窗口的圖形緩沖區(qū)的操作。在這種情況下,這個唯一需要渲染的應(yīng)用程序窗口會通過SurfaceFlinger類的成員函數(shù)setBypassLayer記錄起來。SurfaceFlinger類的成員函數(shù)setBypassLayer的實(shí)現(xiàn)如下所示:[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片voidSurfaceFlinger::setBypassLayer(constsp<LayerBase>&layer){//ifthislayerisalreadythebypasslayer,donothingsp<Layer>cur(mBypassLmote());if(mBypassLayer==layer){if(cur!=NULL){cur->updateBuffersOrientation();}return;}//clearthecurrentbypasslayermBypassLayer.clear();if(cur!=0){cur->setBypass(false);cur.clear();}//setnewbypasslayerif(layer!=0){if(layer->setBypass(true)){mBypassLayer=static_cast<Layer*>(layer.get());}}}這個函數(shù)定義在文件frameworks/base/services/surfaceflinger/SurfaceFlinger.cpp中。從這里就可以看出,在指定了編譯宏USE_COMPOSITION_BYPASS的情況下,SurfaceFlinger服務(wù)唯一需要渲染的應(yīng)用程序窗口就保存在SurfaceFlinger類的一個類型為Layer的成員變量mBypassLayer中,并且會調(diào)用用來這個Layer對象的成員函數(shù)setBypass來將它里面的一個成員變量mBypassState的值設(shè)置為true。在后面的第3部分內(nèi)容中,我們再詳細(xì)分析這個唯一需要渲染的應(yīng)用程序窗口的圖形緩沖區(qū)是如何直接渲染到硬件幀緩沖區(qū)中去的。接下來,我們就繼續(xù)分析SurfaceFlinger類的成員函數(shù)lockPageFlip、computeVisibleRegions和unlockPageFlip的實(shí)現(xiàn),以便可以分別了解各個應(yīng)用程序窗口是如何設(shè)置自己當(dāng)前需要渲染的圖形緩沖區(qū)的、SurfaceFlinger服務(wù)是如何計算各個應(yīng)用程序窗口的可見區(qū)域的,以及各個應(yīng)用程序窗口的可見區(qū)域計算完成之后的善后工作是什么。Step2.SurfaceFlinger.lockPageFlip[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片boolSurfaceFlinger::lockPageFlip(constLayerVector¤tLayers)boolrecomputeVisibleRegions=false;size_tcount=currentLayers.size();sp<LayerBase>const*layers=currentLayers.array();for(size_ti=0;i<count;i++){constsp<LayerBase>&layer(layers[i]);layer->lockPageFlip(recomputeVisibleRegions);}returnrecomputeVisibleRegions;}這個函數(shù)定義在文件frameworks/base/services/surfaceflinger/SurfaceFlinger.cpp中。在前面的一系列文章中,我們假設(shè)在SurfaceFlinger服務(wù)這一側(cè),每一個應(yīng)用程序窗口都是使用一個Layer對象來描述,這些Layer對象都是從LayerBase繼承下來的,因此它們可以保存在一個類型為LayerBase的向量中。從前面的調(diào)用過程可以知道,參數(shù)currentLayers里面保存的一系列LayerBase對象正是用來描述系統(tǒng)當(dāng)前的各個應(yīng)用程序窗口的,SurfaceFlinger類的成員函數(shù)lockPageFlip依次調(diào)用這些LayerBase對象的成員函數(shù)lockPageFlip來讓它們設(shè)置當(dāng)前需要渲染的圖形緩沖區(qū)。由于前面我們假設(shè)這些LayerBase對象的實(shí)際類型為Layer,因此,前面調(diào)用的實(shí)際上就是Layer類的成員函數(shù)lockPageFlip。接下來,我們就繼續(xù)分析Layer類的成員函數(shù)lockPageFlip的實(shí)現(xiàn)。Step3.Layer.lockPageFlip這個函數(shù)定義在文件frameworks/base/services/surfaceflinger/Layer.cpp中。在前面一文中,我們已經(jīng)分析過這個函數(shù)的實(shí)現(xiàn)了,不過當(dāng)時分析得不是太完整,現(xiàn)在我們再重新來閱讀一下。這個函數(shù)比較長,我們分段來閱讀:[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片voidLayer::lockPageFlip(bool&recomputeVisibleRegions){ClientRef::AccesssharedClient(mUserClientRef);SharedBufferServer*lcblk(sharedClient.get());if(!lcblk){//clientdiedrecomputeVisibleRegions=true;return;}ssize_tbuf=lcblk->retireAndLock();if(buf==NOT_ENOUGH_DATA){//NOTE:Thisisnotanerror,itsimplymeansthereisnothingto//retire.Thebufferislockedbecausewewilluseit//forcompositionlaterintheloopreturn;if(buf<NO_ERROR){LOGE("retireAndLock()bufferindex(%d)outofrange",int(buf));mPostedDirtyRegion.clear();return;}//weretiredabuffer,whichbecomesthenewfrontbufferif(mBufferManager.

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論