GUI/BufferQueueProducer 之 buf 产生者
第一个问题,何为Producer?
我们先看一下BufferQueueProducer
类的关键成员函数:
requestBuffer
返回slot对应的GraphicBuffer.正常情况下,dequeuBuffer会返回一个slot值,然后我们按照这个slot值取请求
GraphicBuffer.如果之前的dequeueBuffer返回flags揭示之前的buffer不再合法,一定要再次调用requestBuffer函数.
dequeueBuffer
为BufferQueueProducer拿到下一个buffer的index。从BufferQueue中。
outFense是说,只有在NO_FENSE时候,才能立即写。其他的情况会返回-EBUSY.
width,height,format,musage是描述buffer的属性。
返回值如果是OK的话,紧接着调用requestBuffer拿到对应这个槽的buffer。
queueBuffer
会把填充好的buffer放到BufferQueue中。
需要一个timeStamp做输入,描述buffer,单位ns。
输出是含有buffer信息的结构,包括已经queued的buffer的个数。
Query
寻味native window的属性。输入window.h定义的,比如NATIVE_WINDOW_FORMAT
Connect
尝试链接producer api到bufferQueue中。填充app的listener。
一般的步骤:
- 先调用dequeueBuffer拿到一个slot;
- 然后依据这个slot,调用requestBuffer,拿到buffer。
重要数据结构:
mSlot,它是BufferSlot结构。
namespace android {
class BufferQueueCore;
namespace BufferQueueDefs {
enum { NUM_BUFFER_SLOTS = 64 };
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) {
}
// 指向分配的GraphicBuffer
sp<GraphicBuffer> mGraphicBuffer;
// 用来构建 EGLSyncKHR 对象组
EGLDisplay mEglDisplay;
// 当前这个slot的状态
BufferState mBufferState;
// debug用,描述了producer曾发起过requestBuffer请求.
bool mRequestBufferCalled;
// mFrameNumber 该slot上装的frame的framenumber,可以利用它以LRU顺序dequeue buffer
uint64_t mFrameNumber;
// EGL同步对象.必须保证在slot槽dequeue之前触发(signal).
EGLSyncKHR mEglFence;
// 同步信号.揭示上任主人的读写操作是否完成.如果是free态,说明上个consumer的读完成了,或者上个
Producer的写完成了.
sp<Fence> mFence;
// buffer是否被consumer请求过.
bool mAcquireCalled;
// 是否需要在不通知producer的情况下重新分配buffer,可能是由于现有的buffer的尺寸,用途不合适.
bool mNeedsReallocation;
};
mCore是什么?
所谓的mCore,其实是BufferQueueCore
结构 。它主要是几个数据成员:mFreeSlots
、 mFreeBuffers
以及mActiveBuffers
。他们都是int
型 数组,数据成员是slot的id。
所谓的slot,是SlotType
数组,共64个SlotType
的结构 。每个SlotType
的结构都含有mGraphicBuffer
。
这几个结构的区别是:
mFreeSlots
描述的一组slot id,他们是free并没有关联的buffer。mFreeBuffers
描述的一组slot id,他们是free但有关联的buffer。mActiveBuffers
描述一组有non-free态buffer的slot id。mSharedBufferSlot
描述一个shared的GraphicBuffer
,所谓共享是在“物理内存”层面的共享。
class BufferQueueCore : public virtual RefBase {
// mFreeSlots contains all of the slots which are FREE and do not currently
// have a buffer attached.
// 包含所有free态的并且尚未和buffer attached的slot id
std::set<int> mFreeSlots;
// mFreeBuffers contains all of the slots which are FREE and currently have
// a buffer attached.
// 包含所有free态的并且已有buffer attached上的slot id
std::list<int> mFreeBuffers;
// mUnusedSlots contains all slots that are currently unused. They should be
// free and not have a buffer attached.
// 尚未使用的slot id ,他们是free并且没有buffer attached上的.
std::list<int> mUnusedSlots;
// mActiveBuffers contains all slots which have a non-FREE buffer attached.
// 含有所有非free态buffer attached的slot id
std::set<int> mActiveBuffers;
// mDequeueCondition is a condition variable used for dequeueBuffer in
// synchronous mode.
mutable Condition mDequeueCondition;
// 是否该slot使能了共享模式.
bool mSharedBufferMode;
// When shared buffer mode is enabled, this indicates whether the consumer
// should acquire buffers even if BufferQueue doesn't indicate that they are
// available.
bool mAutoRefresh;
// When shared buffer mode is enabled, this tracks which slot contains the
// shared buffer.
// 共享buf模式使能时,揭示究竟是哪一个BufferSlot关联的是共享buf,它也是个slot的id.
int mSharedBufferSlot;
}