源碼位置
/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狀態,表示此緩沖區正在共享緩沖區模式下使用
狀態轉換示意圖
BufferQueue種有幾個隊列大概解釋
/frameworks/native/libs/gui/include/gui/BufferQueueCore.h
// mSlots is an array of buffer slots that must be mirrored on the producer // side. This allows buffer ownership to be transferred between the producer // and consumer without sending a GraphicBuffer over Binder. The entire // array is initialized to NULL at construction time, and buffers are // allocated for a slot when requestBuffer is called with that slot's index.
// typedef BufferSlot SlotsType[NUM_BUFFER_SLOTS];
// static constexpr int NUM_BUFFER_SLOTS = 64;
BufferQueueDefs::SlotsType mSlots; // mQueue is a FIFO of queued buffers used in synchronous mode.
Fifo mQueue; // mFreeSlots contains all of the slots which are FREE and do not currently // have a buffer attached.
std::set<int> mFreeSlots; // mFreeBuffers contains all of the slots which are FREE and currently have // a buffer attached.
std::list<int> mFreeBuffers; // mUnusedSlots contains all slots that are currently unused. They should be // free and not have a buffer attached.
std::list<int> mUnusedSlots; // mActiveBuffers contains all slots which have a non-FREE buffer attached.
std::set<int> mActiveBuffers;
- mSlots是總的一個buffer隊列
- mActiveBuffers是活躍的,不包含free的狀態的
- mFreeBuffers表示Buffer是Free的,這個序號對應的Buffer已經被分配出來了,只是現在沒有被使用。
- mFreeSlots表示,序號是Free的,這些序號還沒有被用過,說明對應的是沒有Buffer,Buffer還沒有分配。
- mQueue是一個FIFO的隊列,應用(生產者producer)繪制完成后,queue到BufferQueue中,其實就是queue到這個隊列里面