1.BufferQueue内部原理
BufferQueue是IGraphicBufferProducer服务器端的实现;所以BufferQueue会重载IGraphicBufferProducer接口中的各个虚函数queueBuffer,requesBuffer,dequeueBuffer等,该类内部还有一个mSlots[NUM_BUFFER_SLOTS];
1.1 mSlots[NUM_BUFFER_SLOTS]
BufferQueue中BufferSlot的定义:
struct BufferSlot{
//用于记录缓冲区
sp<GraphicBuffer> mGraphicBuffer;
//用于记录缓冲区状态
BufferStatemBuffreState;
...
}
1.2 缓冲区状态
//缓冲区状态
enum BufferState {
//Buffer当前可用,也就是可以被dequeued,此时Buffer的拥有者可以认为是BufferQueue
FREE = 0,
//Buffer已经被dequeued,还没被queued或者canceld,
//此时Buffer的拥有者是应用程序,此时BufferQueue和SurfaceFlinger都不可以操作这块缓冲区
DEQUEUED = 1,
//Buffer被客户端程序queued,不过还不能对它进行dequeue,但可以acquire,
//此时拥有者还是BufferQueue
QUEUED = 2,
//Buffer的拥有者是Consumer,可以被release然后状态回到FREE
ACQUIRED = 3
};
BufferStatemBufferState;
};
1.3 缓冲区状态迁移
BufferQueue :可以认为BufferQueue是一个服务中心,其他两个Owner必须通过它来管理Buffer。 Producer :生产者就是填充Buffer的,通常情况下就是应用程序,应用程序不断刷新UI,从而将产生的数据源源不断的写到Buffer中,当Producer需要一块Buffer时,首先回向中介BufferQueue发起dequeue请求,然后才能对指定的缓冲区进行操作,经过dequeue后的buffer就属于producer了,它可以对缓冲区进行任何操作,而其他Owner不能插手。当producer认为一块Buffer已经写入完成后,将进一步调用BufferQueue的queue接口,把Buffer归还到BufferQueue中,一旦入列成功,Owner就变成了BufferQueue。 Consumer :当一块Buffer就绪之后,Consumer就可以开始工作了。总结:BufferQueue是中介,Producer是内容的产出方,它对Buffer的操作是主动的,Consumer对Buffer的操作是被动的,它必须等到Buffer填充完成之后才工作(其中ready之后通知Consumer的工作是ConsumerListener来完成的),当数据准备就绪后,通过onFrameAvailable通知Consumer来进行消费
class ConsumerListener : public virtualRefBase {
//当一块Buffer可以被消费时,这个函数会被调用
virtual voidonFrameAvailable(const BufferItem& item) = 0;
//BufferQueue通知Cosumer它已经释放slot中一个或多个GraphicBuffer引用
virtual void onBuffersReleased()= 0;
}
2.BufferQueue中缓冲区的分配
2.1 缓冲区分配简略
缓冲区的分配应该既要满足使用者的需求,又要防止浪费。 既然Producer对缓冲区的操作时主动的,那么就意味着它是整个需求的发起者;也就是说只要Producer没有执行dequeueBuffer或者dequeueBuffer时能获取到可用的缓冲区,那就没有必要重新分配空间。
2.2 缓冲区分配的起点Surface::dequeueBuffer
intSurface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {
int buf = -1;
//宽高计算
int reqW = mReqWidth? mReqWidth : mUserWidth;
int reqH =mReqHeight ? mReqHeight : mUserHeight;
sp<Fence>fence;
//dequeueBuffer得到一个缓冲区
status_t result =mGraphicBufferProducer->dequeueBuffer(&buf, &fence,mSwapIntervalZero,reqW, reqH, mReqFormat, mReqUsage);
//buf是一个int值,代表mSlots数组序号
sp<GraphicBuffer>& gbuf(mSlots[buf].buffer);
if (result& IGraphicBufferProducer::RELEASE_ALL_BUFFERS) {
freeAllBuffers();
}
//需要重新分配
if ((result &IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) || gbuf == 0) {
result = mGraphicBufferProducer->requestBuffer(buf, &gbuf);
if (result != NO_ERROR) {
returnresult;
}
}
*buffer =gbuf.get();
return OK;
}
2.3 BpGraphicBufferProducer调用远程服务
class BpGraphicBufferProducer : publicBpInterface<IGraphicBufferProducer>
{
public:
BpGraphicBufferProducer(const sp<IBinder>& impl)
: BpInterface<IGraphicBufferProducer>(impl)
{
}
virtualstatus_t dequeueBuffer(int *buf, sp<Fence>* fence, bool async,
uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
Parcel data, reply;
data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
//只写进去5个参数,这是入参,buf和fence是出参
data.writeInt32(async);
data.writeInt32(w);
data.writeInt32(h);
data.writeInt32(format);
data.writeInt32(usage);
//远程调用
status_t result = remote()->transact(DEQUEUE_BUFFER, data, &reply);
if (result != NO_ERROR) {
return result;
}
*buf= reply.readInt32();//slot编号
bool nonNull = reply.readInt32();
if (nonNull) {
*fence = new Fence();
reply.read(**fence);//从reply中读取数据填充fence
}
result = reply.readInt32();
return result;
}
//这里bufferIdx是入参,传给了服务端,buf是出参
virtual status_trequestBuffer(int bufferIdx, sp<GraphicBuffer>* buf) {
Parcel data, reply;
data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
data.writeInt32(bufferIdx);
status_t result =remote()->transact(REQUEST_BUFFER, data, &reply);
if (result != NO_ERROR) {
return result;
}
bool nonNull = reply.readInt32();//先读取标志位
if (nonNull) {
*buf = new GraphicBuffer();
reply.read(**buf);//从reply中读取数据填充buf
}
result = reply.readInt32();
return result;
}
//...
}
2.4 BnGraphicBufferProducer的响应
status_tBnGraphicBufferProducer::onTransact(
uint32_t code, constParcel& data, Parcel* reply, uint32_t flags)
{
switch(code) {
case DEQUEUE_BUFFER: {
CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
//读取参数
bool async = data.readInt32();
uint32_t w = data.readInt32();
uint32_t h = data.readInt32();
uint32_t format = data.readInt32();
uint32_t usage = data.readInt32();
//注意这两个
int buf;
sp<Fence> fence;
//调用dequeueBuffer
int result = dequeueBuffer(&buf, &fence, async, w, h, format, usage);
//注意写入的顺序,客户端读取的顺序与这个一致
reply->writeInt32(buf);
reply->writeInt32(fence != NULL);
if (fence != NULL) {
reply->write(*fence);
}
reply->writeInt32(result);
return NO_ERROR;
} break;
caseREQUEST_BUFFER: {
CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
int bufferIdx = data.readInt32();
sp<GraphicBuffer> buffer;
//调用requestBuffer
int result = requestBuffer(bufferIdx, &buffer);
reply->writeInt32(buffer != 0);
if (buffer != 0) {
reply->write(*buffer);
}
reply->writeInt32(result);
return NO_ERROR;
} break;
//......
}
}
2.5 BufferQueue::dequeueBuffer真正分配缓冲区
status_t BufferQueue::dequeueBuffer(int*outBuf, sp<Fence>* outFence, bool async,
uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
{
Mutex::Autolocklock(mMutex);
intfound = -1;
bool tryAgain = true;
while (tryAgain) {//查询符合要求的slot
//......
found = INVALID_BUFFER_SLOT;//初始值
int dequeuedCount = 0;
int acquiredCount = 0;
for (int i = 0; i < maxBufferCount; i++) {
const int state = mSlots[i].mBufferState;//该slot的状态
switch (state) {
case BufferSlot::DEQUEUED:
dequeuedCount++;//统计DEQUEUED的slot个数
break;
case BufferSlot::ACQUIRED:
acquiredCount++;
break;
case BufferSlot::FREE: //找到处于空闲状态的slot
if ((found < 0) ||
mSlots[i].mFrameNumber < mSlots[found].mFrameNumber) {
found = i;
}
break;
}
}
if(!mOverrideMaxBufferCount && dequeuedCount) {
//如果client没有设置buffer count的话,就不允许dequeue一个以上buffer
return -EINVAL;
}
//是否需要重试
tryAgain = found == INVALID_BUFFER_SLOT;
if (tryAgain) {
//如果需要重试的话,就等待,因为如果这时候直接开始也是拿不到的
mDequeueCondition.wait(mMutex);
}
}
constint buf = found;
*outBuf = found;//返回值
//成功找到可用序号,接下来就是进行初始化操作以及状态变迁
//BuffreSlot的一个成员mBufferState的赋值
mSlots[buf].mBufferState = BufferSlot::DEQUEUED;
const sp<GraphicBuffer>& buffer(mSlots[buf].mGraphicBuffer);
if ((buffer == NULL) ||
(uint32_t(buffer->width) != w) ||
(uint32_t(buffer->height) != h) ||
(uint32_t(buffer->format) != format) ||
((uint32_t(buffer->usage) & usage) != usage))
{
mSlots[buf].mAcquireCalled = false;
mSlots[buf].mGraphicBuffer = NULL;
mSlots[buf].mRequestBufferCalled = false;
mSlots[buf].mEglFence = EGL_NO_SYNC_KHR;
mSlots[buf].mFence = Fence::NO_FENCE;
mSlots[buf].mEglDisplay = EGL_NO_DISPLAY;
//如果需要重新分配的话,返回值里有BUFFER_NEEDS_REALLOCATION
returnFlags |= IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION;
}
} // endlock scope
//如果需要重新分配的话
if (returnFlags& IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) {
status_t error;
sp<GraphicBuffer> graphicBuffer(
mGraphicBufferAlloc->createGraphicBuffer(w, h, format, usage, &error));
if (graphicBuffer == 0) {
returnerror;
}
{// Scope for the lock
Mutex::Autolock lock(mMutex);
mSlots[*outBuf].mFrameNumber= ~0;
//BufferSlot的另一个重要成员mGraphicBuffer赋值
mSlots[*outBuf].mGraphicBuffer = graphicBuffer;
}
}
returnreturnFlags;
}
分配空间会调用mGraphicBufferAlloc->createGraphicBuffer,如果重新分配了空间,那么需要加上BUFFER_NEEDS_REALLOCATION标志。客户端在使用的时候发现这个标志会调用requestBuffer来取得最新的buffer地址。
2.6 BufferQueue::requestBuffer
status_t BufferQueue::requestBuffer(intslot, sp<GraphicBuffer>* buf) {
//根据索引和状态判断
if (slot < 0 ||slot >= NUM_BUFFER_SLOTS) {
returnBAD_VALUE;
} else if(mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
returnBAD_VALUE;
}
mSlots[slot].mRequestBufferCalled = true;
*buf =mSlots[slot].mGraphicBuffer;//注意buf
return NO_ERROR;
}
requestBuffer后,通过Binder的传递,就把这个buf传给了Surface里gbuf,然后又通过*buffer = gbuf.get();就把这块缓冲区也给了Surface里的buffer
2.7总结
Surface通过dequeueBuffer来申请一块缓冲区,该操作会通过客户端的mGraphicBufferProducer经Binder调用到服务端的BufferQueue(IGraphicBufferProducer的服务端),BufferQueue通过找到一个合适的slot序号并为BufferSlot分配空间,然后通过Binder返回给客户端,客户端通过读取将值传递过去。客户端对缓冲区的操作会通过到服务端使用的是共享内存ashmem。