Android 9.0 BufferQueue中的BufferSlot/BufferState註解

Hi,出發了發表於2021-08-18

原始碼位置

/frameworks/native/libs/gui/include/gui/BufferSlot.h

 

原始碼

struct BufferSlot {

    BufferSlot()
    : mGraphicBuffer(nullptr),
      mEglDisplay(EGL_NO_DISPLAY),
      mBufferState(),
      mRequestBufferCalled(false),
      mFrameNumber(0),
      mEglFence(EGL_NO_SYNC_KHR),
      mFence(Fence::NO_FENCE),
      mAcquireCalled(false),
      mNeedsReallocation(false) {
    }

    // mGraphicBuffer points to the buffer allocated for this slot or is NULL
    // if no buffer has been allocated.
    sp<GraphicBuffer> mGraphicBuffer;

    // mEglDisplay is the EGLDisplay used to create EGLSyncKHR objects.
    EGLDisplay mEglDisplay;

    // mBufferState is the current state of this buffer slot.
    BufferState mBufferState;

    // mRequestBufferCalled is used for validating that the producer did
    // call requestBuffer() when told to do so. Technically this is not
    // needed but useful for debugging and catching producer bugs.
    bool mRequestBufferCalled;

    // mFrameNumber is the number of the queued frame for this slot.  This
    // is used to dequeue buffers in LRU order (useful because buffers
    // may be released before their release fence is signaled).
    uint64_t mFrameNumber;

    // mEglFence is the EGL sync object that must signal before the buffer
    // associated with this buffer slot may be dequeued. It is initialized
    // to EGL_NO_SYNC_KHR when the buffer is created and may be set to a
    // new sync object in releaseBuffer.  (This is deprecated in favor of
    // mFence, below.)
    EGLSyncKHR mEglFence;

    // mFence is a fence which will signal when work initiated by the
    // previous owner of the buffer is finished. When the buffer is FREE,
    // the fence indicates when the consumer has finished reading
    // from the buffer, or when the producer has finished writing if it
    // called cancelBuffer after queueing some writes. When the buffer is
    // QUEUED, it indicates when the producer has finished filling the
    // buffer. When the buffer is DEQUEUED or ACQUIRED, the fence has been
    // passed to the consumer or producer along with ownership of the
    // buffer, and mFence is set to NO_FENCE.
    sp<Fence> mFence;

    // Indicates whether this buffer has been seen by a consumer yet
    bool mAcquireCalled;

    // Indicates whether the buffer was re-allocated without notifying the
    // producer. If so, it needs to set the BUFFER_NEEDS_REALLOCATION flag when
    // dequeued to prevent the producer from using a stale cached buffer.
    bool mNeedsReallocation;
};

成員註解

  • sp<GraphicBuffer> mGraphicBuffer;   // mGraphicBuffer指向這個槽位分配的緩衝區,如果沒有分配緩衝區則為NULL
  • EGLDisplay mEglDisplay;  // 用於建立EGLSyncKHR物件的EGLDisplay
  • BufferState mBufferState; // 緩衝槽的當前狀態
  • bool mRequestBufferCalled; // mRequestBufferCalled用於驗證生產者是否在被告知時呼叫了requestBuffer()。從技術上講,這不是必需的,但對於除錯和捕獲生產者bug非常有用。
  • uint64_t mFrameNumber; // mFrameNumber是此插槽的排隊幀編號。這用於按LRU順序將緩衝區出列(很有用,因為緩衝區可能在釋放圍欄發出訊號之前被釋放)。
  • EGLSyncKHR mEglFence; // mEglFence是EGL sync物件,必須在與此緩衝槽關聯的緩衝區退出佇列之前發出訊號。當建立緩衝區時,它被初始化為EGL_NO_SYNC_KHR,並且可以設定為releaseBuffer中的新同步物件(支援mFence時mEglFence被棄用)
  • sp<Fence> mFence;  // mFence是一個圍欄,當緩衝區的前所有者啟動的工作完成時,它將發出訊號。
  1. 當Buffer處在FREE時,Fence指示消費者何時已完成從緩衝區的讀取,或者生產者何時已完成寫入
  2. 當Buffer處在QUEUED時,它指示生產者何時完成緩衝區填充。
  3. 當Buffer處在DEQUEUED or ACQUIRED時,Fence連同緩衝區的所有權一起傳遞給消費者或生產者,並且mFence設定為NO_FENCE。
  • bool mAcquireCalled; // 指示消費者consumer是否已看到此緩衝區
  • bool mNeedsReallocation; //指示是否在未通知生產者的情況下重新分配了緩衝區。如果是這樣,它需要在退出佇列時設定BUFFER_NEEDS_REALLOCATION標誌,以防止生產者使用過時的快取緩衝區。

 

buffer的狀態BufferState

原始碼位置

/frameworks/native/libs/gui/include/gui/BufferSlot.h

一個buffer有5種可能的狀態:FREE/DEQUEUED/QUEUED/ACQUIRED/SHARED

    // A buffer can be in one of five states, represented as below:
    //
    //         | mShared | mDequeueCount | mQueueCount | mAcquireCount |
    // --------|---------|---------------|-------------|---------------|
    // FREE    |  false  |       0       |      0      |       0       |
    // DEQUEUED|  false  |       1       |      0      |       0       |
    // QUEUED  |  false  |       0       |      1      |       0       |
    // ACQUIRED|  false  |       0       |      0      |       1       |
    // SHARED  |  true   |      any      |     any     |      any      |
    //
    // FREE indicates that the buffer is available to be dequeued by the
    // producer. The slot is "owned" by BufferQueue. It transitions to DEQUEUED
    // when dequeueBuffer is called.
    //
    // DEQUEUED indicates that the buffer has been dequeued by the producer, but
    // has not yet been queued or canceled. The producer may modify the
    // buffer's contents as soon as the associated release fence is signaled.
    // The slot is "owned" by the producer. It can transition to QUEUED (via
    // queueBuffer or attachBuffer) or back to FREE (via cancelBuffer or
    // detachBuffer).
    //
    // QUEUED indicates that the buffer has been filled by the producer and
    // queued for use by the consumer. The buffer contents may continue to be
    // modified for a finite time, so the contents must not be accessed until
    // the associated fence is signaled. The slot is "owned" by BufferQueue. It
    // can transition to ACQUIRED (via acquireBuffer) or to FREE (if another
    // buffer is queued in asynchronous mode).
    //
    // ACQUIRED indicates that the buffer has been acquired by the consumer. As
    // with QUEUED, the contents must not be accessed by the consumer until the
    // acquire fence is signaled. The slot is "owned" by the consumer. It
    // transitions to FREE when releaseBuffer (or detachBuffer) is called. A
    // detached buffer can also enter the ACQUIRED state via attachBuffer.
    //
    // SHARED indicates that this buffer is being used in shared buffer
    // mode. It can be in any combination of the other states at the same time,
    // except for FREE (since that excludes being in any other state). It can
    // also be dequeued, queued, or acquired multiple times.
  • FREE狀態,buffer及slot屬於BufferQueue,producer可以通過呼叫dequeueBuffer獲取該buffer,其狀態轉為DEQUEUED
  • DEQUEUED狀態,表示該buffer已經被producer出佇列,但時還被queued或canceled。一旦與該buffer相關聯的fence發出訊號,producer就可以修改buffer的內容。這種狀態下slot屬於producer所有,當呼叫queueBuffer or attachBuffer後轉為QUEUED,或呼叫cancelBuffer or detachBuffer轉為FREE
  • QUEUED狀態,表示該buffer已經被producer填充資料,入佇列讓consumer使用。buffer內容可能會在有限的時間內繼續修改,因此在相關fence發出訊號之前,不得訪問內容。此時slot歸BufferQueue所有,buffer狀態可以轉為ACQUIRED(via acquireBuffer) 或FREE(另一個buffer非同步模式下入佇列)
  • ACQUIRED狀態,表示該buffer被consumer取得。fence訊號發出後,消費者就可以訪問其內容了。slot被consumer所擁有。 當呼叫releaseBuffer (or detachBuffer)可以轉為FREE
  • SHARED狀態,表示此緩衝區正在共享緩衝區模式下使用

 狀態轉換示意圖

 

相關文章