源码位置
/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到这个队列里面