Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android系統教程 >> Android開發教程 >> Android GUI系統之SurfaceFlinger(6) BufferQueue中的緩沖區分配

Android GUI系統之SurfaceFlinger(6) BufferQueue中的緩沖區分配

編輯:Android開發教程

1.1.1 BufferQueue中的緩沖區分配

我們知道,BufferQueue中有一個mSlots數組用於管理其內的各緩沖區,最大容量為32。從它的聲明方式來看,這個mSlots在程序一開始就靜態分配了32個BufferSlot大小的空間。不過這並不代表緩沖區也是一次性靜態分配的,恰恰相反,從BufferSlot的內部變量指針mGraphicBuffer可以看出,緩沖區的空間分配應當是動態的(從下面的注釋也能看出一些端倪):

// mGraphicBuffer points to the buffer allocated for this slot or isNULL if no buffer has been allocated.

sp<GraphicBuffer> mGraphicBuffer;

現在的問題就轉移為,在什麼情況下會給一個Slot實際的分配空間呢?

首先能想到的就是dequeueBuffer。理由如下:

緩沖區的空間分配應該既要滿足使用者的需求,又要防止浪費。後面這一點mSlots已經滿足了,因為它並沒有采取一開始就靜態預分配的方式

既然Producer對buffer的操作是“主動”的,那麼就意味著它是整個需求的發起者。換句話說,只要它沒有dequeueBuffer,或者dequeueBuffer時能獲取到可用的緩沖區,那當然就沒有必要再重新分配空間了

來詳細分析下這個函數:

/*frameworks/native/libs/gui/BufferQueue.cpp*/

status_t BufferQueue::dequeueBuffer(int *outBuf, uint32_t w,uint32_t h, uint32_t format, uint32_t usage) {…

status_t  returnFlags(OK);

   { // Scope for the lock

       Mutex::Autolocklock(mMutex); /*這裡采用了自動鎖,所以上面需要加個“{”,這樣當lock變量生

                                  命期結束後鎖也就自動釋放了。這種寫法非常常見*/

                  …

       int found = -1;

       int foundSync = -1;

       int dequeuedCount = 0;

       bool tryAgain = true;

       while (tryAgain) {/*Step1. 循環查找符合要求的slot*/

           …                        

           found = INVALID_BUFFER_SLOT;//初始值

           foundSync =INVALID_BUFFER_SLOT;

           dequeuedCount = 0;          

           for (int i = 0; i< mBufferCount; i++) {

               const intstate = mSlots[i].mBufferState;

               /*Step2.統計dequeued buffer數量,後面會用到*/

               if (state ==BufferSlot::DEQUEUED) {

                   dequeuedCount++;

               }

             

               if (false) {

                  //肯定不會走這邊

               } else {

                   if (state== BufferSlot::FREE) { /*Step3.尋找符合要求的Slot*/                      

                       boolisOlder = mSlots[i].mFrameNumber <mSlots[found].mFrameNumber;

                       if(found < 0 || isOlder) {

                          foundSync = i;

                           found = i; //找到符合要求的Slot

                       }

                   }// if (state ==BufferSlot::FREE)結束

               }//if(false)else結束

           }// for循環結束

          /*Step4.如果Client沒有設置buffer count的話,就不允許dequeue一個以上的buffer*/

           if(!mClientBufferCount && dequeuedCount) {

               ST_LOGE("dequeueBuffer:can't dequeue multiple buffers without setting the buffer count");

               return-EINVAL;

           }

           …

           /*Step5. 判斷是否要重試*/

           tryAgain = found== INVALID_BUFFER_SLOT;

           if (tryAgain) {

               mDequeueCondition.wait(mMutex);

           }

       }//while循環結束

       if (found ==INVALID_BUFFER_SLOT) {

           /*因為前面while循環如果沒找到的話是不會返回的,所以理論上不會出現這種情況*/

          ST_LOGE("dequeueBuffer: no available buffer slots");

           return -EBUSY;

       }

       const int buf = found;

       *outBuf = found; //返回值

      /*成功找到可用的Slot序號,接下來就開始對這個指定的Slot進行初始操作,及狀態變遷等*/

                  …

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