原始碼位置
/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是一個圍欄,當緩衝區的前所有者啟動的工作完成時,它將發出訊號。
- 當Buffer處在FREE時,Fence指示消費者何時已完成從緩衝區的讀取,或者生產者何時已完成寫入
- 當Buffer處在QUEUED時,它指示生產者何時完成緩衝區填充。
- 當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狀態,表示此緩衝區正在共享緩衝區模式下使用
狀態轉換示意圖