BufferQueue介绍
生产者(一般是app):
1.通过queueBuffer方法从BufferQueue拿到一个Buffer
2.绘制Buffer
3.通过dequeueBuffer方法将绘制好的Buffer传给BufferQueue
消费者(一般是SurfaceFlinger):
1.通过acquireBuffer方法从BufferQueue拿到一个绘制好了的Buffer
2.使用Buffer(SurfaceFlinger让Buffer参与图像合成,最终显示到屏幕上)
3.通过releaseBuffer方法将用过的Buffer传给BufferQueue
Buffer一般有4种状态:
1.FREE
2.DEQUEUED
3.QUEUED
4.ACQUIRED
BufferQueue相关重要类
首先看实现者BufferQueueCore的定义(frameworks/native/libs/gui/include/gui/BufferQueueCore.h、frameworks/native/libs/gui/BufferQueueCore.cpp):
class BufferQueueCore : public virtual RefBase {
friend class BufferQueueProducer;
friend class BufferQueueConsumer;
public:
......
typedef Vector<BufferItem> Fifo;
// BufferQueueCore manages a pool of gralloc memory slots to be used by
// producers and consumers.
BufferQueueCore();
virtual ~BufferQueueCore();
private:
......
// 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.
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;
......
}
BufferQueueCore::BufferQueueCore(): ...... {
int numStartingBuffers = getMaxBufferCountLocked();
for (int s = 0; s < numStartingBuffers; s++) {
mFreeSlots.insert(s);
}
for (int s = numStartingBuffers; s < BufferQueueDefs::NUM_BUFFER_SLOTS; s++) {
mUnusedSlots.push_front(s);
}
}
这里成员变量mSlots用BufferSlot存储GraphicBuffer,其中BufferSlot定义如下(frameworks/native/libs/gui/include/gui/BufferQueueDefs.h、frameworks/native/libs/gui/include/gui/BufferSlot.h):
namespace android {
class BufferQueueCore;
namespace BufferQueueDefs {
typedef BufferSlot SlotsType[NUM_BUFFER_SLOTS];
} // namespace BufferQueueDefs
} // namespace android
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;
};
记录Buffer状态的BufferState类定义如下(frameworks/native/libs/gui/include/gui/BufferSlot.h):
// BufferState tracks the states in which a buffer slot can be.
struct BufferState {
// All slots are initially FREE (not dequeued, queued, acquired, or shared).
BufferState()
: mDequeueCount(0),
mQueueCount(0),
mAcquireCount(0),
mShared(false) {
}
uint32_t mDequeueCount;
uint32_t mQueueCount;
uint32_t mAcquireCount;
bool mShared;
// 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.
inline bool isFree() const {
return !isAcquired() && !isDequeued() && !isQueued();
}
inline bool isDequeued() const {
return mDequeueCount > 0;
}
inline bool isQueued() const {
return mQueueCount > 0;
}
inline bool isAcquired() const {
return mAcquireCount > 0;
}
inline bool isShared() const {
return mShared;
}
inline void reset() {
*this = BufferState();
}
const char* string() const;
inline void dequeue()