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() {
mDequeueCount++;
}
inline void detachProducer() {
if (mDequeueCount > 0) {
mDequeueCount--;
}
}
inline void attachProducer() {
mDequeueCount++;
}
inline void queue() {
if (mDequeueCount > 0) {
mDequeueCount--;
}
mQueueCount++;
}
inline void cancel() {
if (mDequeueCount > 0) {
mDequeueCount--;
}
}
inline void freeQueued() {
if (mQueueCount > 0) {
mQueueCount--;
}
}
inline void acquire() {
if (mQueueCount > 0) {
mQueueCount--;
}
mAcquireCount++;
}
inline void acquireNotInQueue() {
mAcquireCount++;
}
inline void release() {
if (mAcquireCount > 0) {
mAcquireCount--;
}
}
inline void detachConsumer() {
if (mAcquireCount > 0) {
mAcquireCount--;
}
}
inline void attachConsumer() {
mAcquireCount++;
}
};
BufferSlot中存储的GraphicBuffer定义如下(frameworks/native/libs/ui/include/ui/GraphicBuffer.h):
class GraphicBuffer
: public ANativeObjectBase<ANativeWindowBuffer, GraphicBuffer, RefBase>,
public Flattenable<GraphicBuffer>
{
friend class Flattenable<GraphicBuffer>;
public:
enum {
USAGE_SW_READ_NEVER = GRALLOC_USAGE_SW_READ_NEVER,
USAGE_SW_READ_RARELY = GRALLOC_USAGE_SW_READ_RARELY,
USAGE_SW_READ_OFTEN = GRALLOC_USAGE_SW_READ_OFTEN,
USAGE_SW_READ_MASK = GRALLOC_USAGE_SW_READ_MASK,
USAGE_SW_WRITE_NEVER = GRALLOC_USAGE_SW_WRITE_NEVER,
USAGE_SW_WRITE_RARELY = GRALLOC_USAGE_SW_WRITE_RARELY,
USAGE_SW_WRITE_OFTEN = GRALLOC_USAGE_SW_WRITE_OFTEN,
USAGE_SW_WRITE_MASK = GRALLOC_USAGE_SW_WRITE_MASK,
USAGE_SOFTWARE_MASK = USAGE_SW_READ_MASK|USAGE_SW_WRITE_MASK,
USAGE_PROTECTED = GRALLOC_USAGE_PROTECTED,
USAGE_HW_TEXTURE = GRALLOC_USAGE_HW_TEXTURE,
USAGE_HW_RENDER = GRALLOC_USAGE_HW_RENDER,
USAGE_HW_2D = GRALLOC_USAGE_HW_2D,
USAGE_HW_COMPOSER = GRALLOC_USAGE_HW_COMPOSER,
USAGE_HW_VIDEO_ENCODER = GRALLOC_USAGE_HW_VIDEO_ENCODER,
USAGE_HW_MASK = GRALLOC_USAGE_HW_MASK,
USAGE_CURSOR = GRALLOC_USAGE_CURSOR,
};
static sp<GraphicBuffer> from(ANativeWindowBuffer *);
static GraphicBuffer* fromAHardwareBuffer(AHardwareBuffer*);
static GraphicBuffer const* fromAHardwareBuffer(AHardwareBuffer const*);
AHardwareBuffer* toAHardwareBuffer();
AHardwareBuffer const* toAHardwareBuffer() const;
// Create a GraphicBuffer to be unflatten'ed into or be reallocated.
GraphicBuffer();
// Create a GraphicBuffer by allocating and managing a buffer internally.
// This function is privileged. See reallocate for details.
GraphicBuffer(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
uint32_t inLayerCount, uint64_t inUsage,
std::string requestorName = "<Unknown>");
// Create a GraphicBuffer from an existing handle.
enum HandleWrapMethod : uint8_t {
// Wrap and use the handle directly. It assumes the handle has been
// registered and never fails. The handle must have a longer lifetime
// than this wrapping GraphicBuffer.
//
// This can be used when, for example, you want to wrap a handle that
// is already managed by another GraphicBuffer.
WRAP_HANDLE,
// Take ownership of the handle and use it directly. It assumes the
// handle has been registered and never fails.
//
// This can be used to manage an already registered handle with
// GraphicBuffer.
TAKE_HANDLE,
// Take onwership of an unregistered handle and use it directly. It
// can fail when the buffer does not register. There is no ownership
// transfer on failures.
//
// This can be used to, for example, create a GraphicBuffer from a
// handle returned by Parcel::readNativeHandle.
TAKE_UNREGISTERED_HANDLE,
// Make a clone of the handle and use the cloned handle. It can fail
// when cloning fails or when the buffer does not register. There is
// never ownership transfer.
//
// This can be used to create a GraphicBuffer from a handle that
// cannot be used directly, such as one from hidl_handle.
CLONE_HANDLE,
};
GraphicBuffer(const native_handle_t* inHandle, HandleWrapMethod method, uint32_t inWidth,
uint32_t inHeight, PixelFormat inFormat, uint32_t inLayerCount, uint64_t inUsage,
uint32_t inStride);
// These functions are deprecated because they only take 32 bits of usage
GraphicBuffer(const native_handle_t* inHandle, HandleWrapMethod method, uint32_t inWidth,
uint32_t inHeight, PixelFormat inFormat, uint32_t inLayerCount, uint32_t inUsage,
uint32_t inStride)
: GraphicBuffer(inHandle, method, inWidth, inHeight, inFormat, inLayerCount,
static_cast<uint64_t>(inUsage), inStride) {}
GraphicBuffer(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
uint32_t inLayerCount, uint32_t inUsage, uint32_t inStride,
native_handle_t* inHandle, bool keepOwnership);
GraphicBuffer(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
uint32_t inUsage, std::string requestorName = "<Unknown>");
// return status
status_t initCheck() const;
uint32_t getWidth() const { return static_cast<uint32_t>(width); }
uint32_t getHeight() const { return static_cast<uint32_t>(height); }
uint32_t getStride() const { return static_cast<uint32_t>(stride); }
uint64_t getUsage() const { return usage; }
PixelFormat getPixelFormat() const { return format; }
uint32_t getLayerCount() const { return static_cast<uint32_t>(layerCount); }
Rect getBounds() const { return Rect(width, height); }
uint64_t getId() const { return mId; }
uint32_t getGenerationNumber() const { return mGenerationNumber; }
void setGenerationNumber(uint32_t generation) {
mGenerationNumber = generation;
}
// This function is privileged. It requires access to the allocator
// device or service, which usually involves adding suitable selinux
// rules.
status_t reallocate(uint32_t inWidth, uint32_t inHeight,
PixelFormat inFormat, uint32_t inLayerCount, uint64_t inUsage);
bool needsReallocation(uint32_t inWidth, uint32_t inHeight,
PixelFormat inFormat, uint32_t inLayerCount, uint64_t inUsage);
// For the following two lock functions, if bytesPerStride or bytesPerPixel
// are unknown or variable, -1 will be returned
status_t lock(uint32_t inUsage, void** vaddr, int32_t* outBytesPerPixel = nullptr,
int32_t* outBytesPerStride = nullptr);
status_t lock(uint32_t inUsage, const Rect& rect, void** vaddr,
int32_t* outBytesPerPixel = nullptr, int32_t* outBytesPerStride = nullptr);
// For HAL_PIXEL_FORMAT_YCbCr_420_888
status_t lockYCbCr(uint32_t inUsage, android_ycbcr *ycbcr);
status_t lockYCbCr(uint32_t inUsage, const Rect& rect,
android_ycbcr *ycbcr);
status_t unlock();
// For the following three lockAsync functions, if bytesPerStride or bytesPerPixel
// are unknown or variable, -1 will be returned
status_t lockAsync(uint32_t inUsage, void** vaddr, int fenceFd,
int32_t* outBytesPerPixel = nullptr, int32_t* outBytesPerStride = nullptr);
status_t lockAsync(uint32_t inUsage, const Rect& rect, void** vaddr, int fenceFd,
int32_t* outBytesPerPixel = nullptr, int32_t* outBytesPerStride = nullptr);
status_t lockAsync(uint64_t inProducerUsage, uint64_t inConsumerUsage, const Rect& rect,
void** vaddr, int fenceFd, int32_t* outBytesPerPixel = nullptr,
int32_t* outBytesPerStride = nullptr);
status_t lockAsyncYCbCr(uint32_t inUsage, android_ycbcr *ycbcr,
int fenceFd);
status_t lockAsyncYCbCr(uint32_t inUsage, const Rect& rect,
android_ycbcr *ycbcr, int fenceFd);
status_t unlockAsync(int *fenceFd);
status_t isSupported(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
uint32_t inLayerCount, uint64_t inUsage, bool* outSupported) const;
ANativeWindowBuffer* getNativeBuffer() const;
// for debugging
static void dumpAllocationsToSystemLog();
// Flattenable protocol
size_t getFlattenedSize() const;
size_t getFdCount() const;
status_t flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const;
status_t unflatten(void const*& buffer, size_t& size, int const*& fds, size_t& count);
GraphicBufferMapper::Version getBufferMapperVersion() const {
return mBufferMapper.getMapperVersion();
}
void addDeathCallback(GraphicBufferDeathCallback deathCallback, void* context);
private:
~GraphicBuffer();
enum {
ownNone = 0,
ownHandle = 1,
ownData = 2,
};
inline const GraphicBufferMapper& getBufferMapper() const {
return mBufferMapper;
}
inline GraphicBufferMapper& getBufferMapper() {
return mBufferMapper;
}
uint8_t mOwner;
private:
friend class Surface;
friend class BpSurface;
friend class BnSurface;
friend class LightRefBase<GraphicBuffer>;
GraphicBuffer(const GraphicBuffer& rhs);
GraphicBuffer& operator = (const GraphicBuffer& rhs);
const GraphicBuffer& operator = (const GraphicBuffer& rhs) const;
status_t initWithSize(uint32_t inWidth, uint32_t inHeight,
PixelFormat inFormat, uint32_t inLayerCount,
uint64_t inUsage, std::string requestorName);
status_t initWithHandle(const native_handle_t* inHandle, HandleWrapMethod method,
uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
uint32_t inLayerCount, uint64_t inUsage, uint32_t inStride);
void free_handle();
GraphicBufferMapper& mBufferMapper;
ssize_t mInitCheck;
// numbers of fds/ints in native_handle_t to flatten
uint32_t mTransportNumFds;
uint32_t mTransportNumInts;
uint64_t mId;
// Unused, but removing this may break GSI.
int32_t mBufferId = -1;
// Stores the generation number of this buffer. If this number does not
// match the BufferQueue's internal generation number (set through
// IGBP::setGenerationNumber), attempts to attach the buffer will fail.
uint32_t mGenerationNumber;
// Send a callback when a GraphicBuffer dies.
//
// This is used for BufferStateLayer caching. GraphicBuffers are refcounted per process. When
// A GraphicBuffer doesn't have any more sp<> in a process, it is destroyed. This causes
// problems when trying to implicitcly cache across process boundaries. Ideally, both sides
// of the cache would hold onto wp<> references. When an app dropped its sp<>, the GraphicBuffer
// would be destroyed. Unfortunately, when SurfaceFlinger has only a wp<> reference to the
// GraphicBuffer, it immediately goes out of scope in the SurfaceFlinger process. SurfaceFlinger
// must hold onto a sp<> to the buffer. When the GraphicBuffer goes out of scope in the app's
// process, the client side cache will get this callback. It erases the buffer from its cache
// and informs SurfaceFlinger that it should drop its strong pointer reference to the buffer.
std::vector<std::pair<GraphicBufferDeathCallback, void* /*mDeathCallbackContext*/>>
mDeathCallbacks;
};
接下来看BufferQueue的定义(frameworks/native/libs/gui/include/gui/BufferQueue.h、frameworks/native/libs/gui/BufferQueue.cpp):
class BufferQueue {
public:
// BufferQueue will keep track of at most this value of buffers.
// Attempts at runtime to increase the number of buffers past this will fail.
enum { NUM_BUFFER_SLOTS = BufferQueueDefs::NUM_BUFFER_SLOTS }; // 64
// Used as a placeholder slot# when the value isn't pointing to an existing buffer.
enum { INVALID_BUFFER_SLOT = BufferItem::INVALID_BUFFER_SLOT }; // -1
// Alias to <IGraphicBufferConsumer.h> -- please scope from there in future code!
enum {
NO_BUFFER_AVAILABLE = IGraphicBufferConsumer::NO_BUFFER_AVAILABLE,
PRESENT_LATER = IGraphicBufferConsumer::PRESENT_LATER,
};
// When in async mode we reserve two slots in order to guarantee that the
// producer and consumer can run asynchronously.
enum { MAX_MAX_ACQUIRED_BUFFERS = NUM_BUFFER_SLOTS - 2 };
// for backward source compatibility
typedef ::android::ConsumerListener ConsumerListener;
// ProxyConsumerListener is a ConsumerListener implementation that keeps a weak
// reference to the actual consumer object. It forwards all calls to that
// consumer object so long as it exists.
//
// This class exists to avoid having a circular reference between the
// BufferQueue object and the consumer object. The reason this can't be a weak
// reference in the BufferQueue class is because we're planning to expose the
// consumer side of a BufferQueue as a binder interface, which doesn't support
// weak references.
class ProxyConsumerListener : public BnConsumerListener {
public:
explicit ProxyConsumerListener(const wp<ConsumerListener>& consumerListener);
~ProxyConsumerListener() override;
void onDisconnect() override;
void onFrameAvailable(const BufferItem& item) override;
void onFrameReplaced(const BufferItem& item) override;
void onBuffersReleased() override;
void onSidebandStreamChanged() override;
void onFrameDequeued(const uint64_t bufferId) override;
void onFrameCancelled(const uint64_t bufferId) override;
void onFrameDetached(const uint64_t bufferID) override;
void addAndGetFrameTimestamps(
const NewFrameEventsEntry* newTimestamps,
FrameEventHistoryDelta* outDelta) override;
private:
// mConsumerListener is a weak reference to the IConsumerListener. This is
// the raison d'etre of ProxyConsumerListener.
wp<ConsumerListener> mConsumerListener;
};
// BufferQueue manages a pool of gralloc memory slots to be used by
// producers and consumers. allocator is used to allocate all the
// needed gralloc buffers.
static void createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
sp<IGraphicBufferConsumer>* outConsumer,
bool consumerIsSurfaceFlinger = false);
#ifndef NO_BUFFERHUB
// Creates an IGraphicBufferProducer and IGraphicBufferConsumer pair backed by BufferHub.
static void createBufferHubQueue(sp<IGraphicBufferProducer>* outProducer,
sp<IGraphicBufferConsumer>* outConsumer);
#endif
BufferQueue() = delete; // Create through createBufferQueue
};
void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
sp<IGraphicBufferConsumer>* outConsumer,
bool consumerIsSurfaceFlinger) {
LOG_ALWAYS_FATAL_IF(outProducer == nullptr,
"BufferQueue: outProducer must not be NULL");
LOG_ALWAYS_FATAL_IF(outConsumer == nullptr,
"BufferQueue: outConsumer must not be NULL");
sp<BufferQueueCore> core(new BufferQueueCore());
LOG_ALWAYS_FATAL_IF(core == nullptr,
"BufferQueue: failed to create BufferQueueCore");
sp<IGraphicBufferProducer> producer(new BufferQueueProducer(core, consumerIsSurfaceFlinger));
LOG_ALWAYS_FATAL_IF(producer == nullptr,
"BufferQueue: failed to create BufferQueueProducer");
sp<IGraphicBufferConsumer> consumer(new BufferQueueConsumer(core));
LOG_ALWAYS_FATAL_IF(consumer == nullptr,
"BufferQueue: failed to create BufferQueueConsumer");
*outProducer = producer;
*outConsumer = consumer;
}
通过createBufferQueue方法得到一个BufferQueueProducer和一个BufferQueueConsumer,并且创建了一个BufferQueueCore传给了他们。
Buffer状态转移流程
生产者通过dequeueBuffer拿到slot(frameworks/native/libs/gui/BufferQueueProducer.cpp):
status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* outFence,
uint32_t width, uint32_t height, PixelFormat format,
uint64_t usage, uint64_t* outBufferAge,
FrameEventHistoryDelta* outTimestamps) {
......
{ // Autolock scope
std::unique_lock<std::mutex> lock(mCore->mMutex);
......
int found = BufferItem::INVALID_BUFFER_SLOT;
while (found == BufferItem::INVALID_BUFFER_SLOT) {
status_t status = waitForFreeSlotThenRelock(FreeSlotCaller::Dequeue, lock, &found); // 找可用的FreeSlot
......
}
const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
......
if (mCore->mSharedBufferSlot != found) {
mCore->mActiveBuffers.insert(found);
}
*outSlot = found;
......
mSlots[found].mBufferState.dequeue(); // Buffer的状态变为DEQUEUED
......
if (!(returnFlags & BUFFER_NEEDS_REALLOCATION)) {
if (mCore->mConsumerListener != nullptr) {
mCore->mConsumerListener->onFrameDequeued(mSlots[*outSlot].mGraphicBuffer->getId());
}
}
} // Autolock scope
......
return returnFlags;
}
再通过requestBuffer拿到buffer(frameworks/native/libs/gui/BufferQueueProducer.cpp):
status_t BufferQueueProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
......
std::lock_guard<std::mutex> lock(mCore->mMutex);
......
mSlots[slot].mRequestBufferCalled = true;
*buf = mSlots[slot].mGraphicBuffer;
return NO_ERROR;
}
buffer绘制完成后,要调用queueBuffer了(frameworks/native/libs/gui/BufferQueueProducer.cpp):
status_t BufferQueueProducer::queueBuffer(int slot,
const QueueBufferInput &input, QueueBufferOutput *output) {
......
{ // Autolock scope
std::lock_guard<std::mutex> lock(mCore->mMutex);
......
const sp<GraphicBuffer>& graphicBuffer(mSlots[slot].mGraphicBuffer);
......
mSlots[slot].mBufferState.queue(); // Buffer的状态变成QUEUED
......
output->bufferReplaced = false;
if (mCore->mQueue.empty()) {
// When the queue is empty, we can ignore mDequeueBufferCannotBlock
// and simply queue this buffer
mCore->mQueue.push_back(item);
frameAvailableListener = mCore->mConsumerListener;
} else {
// When the queue is not empty, we need to look at the last buffer
// in the queue to see if we need to replace it
const BufferItem& last = mCore->mQueue.itemAt(
mCore->mQueue.size() - 1);
if (last.mIsDroppable) {
......
} else {
mCore->mQueue.push_back(item);
frameAvailableListener = mCore->mConsumerListener;
}
}
......
} // Autolock scope
......
{ // scope for the lock
std::unique_lock<std::mutex> lock(mCallbackMutex);
......
if (frameAvailableListener != nullptr) {
frameAvailableListener->onFrameAvailable(item);
} else if (frameReplacedListener != nullptr) {
frameReplacedListener->onFrameReplaced(item);
}
......
}
// Wait without lock held
if (connectedApi == NATIVE_WINDOW_API_EGL) {
// Waiting here allows for two full buffers to be queued but not a
// third. In the event that frames take varying time, this makes a
// small trade-off in favor of latency rather than throughput.
lastQueuedFence->waitForever("Throttling EGL Production");
}
return NO_ERROR;
}
消费者调用acquireBuffer拿到buffer(frameworks/native/libs/gui/BufferQueueConsumer.cpp):
status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer,
nsecs_t expectedPresent, uint64_t maxFrameNumber) {
......
{
std::unique_lock<std::mutex> lock(mCore->mMutex);
......
// In asynchronous mode the list is guaranteed to be one buffer deep,
// while in synchronous mode we use the oldest buffer.
if (mCore->mQueue.empty() && !sharedBufferAvailable) {
return NO_BUFFER_AVAILABLE;
}
BufferQueueCore::Fifo::iterator front(mCore->mQueue.begin());
// If expectedPresent is specified, we may not want to return a buffer yet.
// If it's specified and there's more than one buffer queued, we may want
// to drop a buffer.
// Skip this if we're in shared buffer mode and the queue is empty,
// since in that case we'll just return the shared buffer.
if (expectedPresent != 0 && !mCore->mQueue.empty()) {
......
}
int slot = BufferQueueCore::INVALID_BUFFER_SLOT;
if (sharedBufferAvailable && mCore->mQueue.empty()) {
......
} else {
slot = front->mSlot;
*outBuffer = *front;
}
......
if (!outBuffer->mIsStale) {
mSlots[slot].mAcquireCalled = true;
// Don't decrease the queue count if the BufferItem wasn't
// previously in the queue. This happens in shared buffer mode when
// the queue is empty and the BufferItem is created above.
if (mCore->mQueue.empty()) {
mSlots[slot].mBufferState.acquireNotInQueue();
} else {
mSlots[slot].mBufferState.acquire(); // Buffer状态变为ACQUIRED
}
mSlots[slot].mFence = Fence::NO_FENCE;
}
......
mCore->mQueue.erase(front);
......
}
if (listener != nullptr) {
for (int i = 0; i < numDroppedBuffers; ++i) {
listener->onBufferReleased();
}
}
return NO_ERROR;
}
buffer消费完毕后,要调用releaseBuffer了(frameworks/native/libs/gui/BufferQueueConsumer.cpp):
status_t BufferQueueConsumer::releaseBuffer(int slot, uint64_t frameNumber,
const sp<Fence>& releaseFence, EGLDisplay eglDisplay,
EGLSyncKHR eglFence) {
......
{ // Autolock scope
std::lock_guard<std::mutex> lock(mCore->mMutex);
......
mSlots[slot].mEglDisplay = eglDisplay;
mSlots[slot].mEglFence = eglFence;
mSlots[slot].mFence = releaseFence;
mSlots[slot].mBufferState.release(); // Buffer状态变成FREE
......
// Don't put the shared buffer on the free list.
if (!mSlots[slot].mBufferState.isShared()) {
mCore->mActiveBuffers.erase(slot);
mCore->mFreeBuffers.push_back(slot);
}
......
} // Autolock scope
// Call back without lock held
if (listener != nullptr) {
listener->onBufferReleased();
}
return NO_ERROR;
}
本文详细介绍了Android系统中BufferQueue的工作原理及其内部实现机制。主要内容包括BufferQueue的基本概念、Buffer的状态流转过程、生产者与消费者的交互流程等。对于理解Android系统的绘图机制具有重要意义。
8715

被折叠的 条评论
为什么被折叠?



