BufferQueue 的管理
1),对buffer的管理符合“生产者-消费者”模型,这里有以下几个相关的类:
BufferQueueProducer.cpp是IGraphicBufferProducer对应服务端的实现,负责缓冲区的申请。
BufferQueueConsumer.cpp是IGraphicBufferProducer对应的服务端的实现,是buffer消费者。
BufferQueueCore.cpp,可以看作是Buffer的中枢,一方面BufferqueueProducer对buffer的申请也是通过BufferQueueCore来实现的,具体是BufferQueueCore中的GraphicBufferAlloc。另一方面,当有可以消费的buffer时,是通过BufferQueueCore通知到BufferQueueConsumer,具体是通过ConsumerListener来实现的。
GraphicBufferAlloc.cpp是IGraphicBufferAlloc对应的服务端的实现,负责GraphicBuffer的申请。
既然说BufferQueueCore中的GraphicBufferAlloc负责GraphicBuffer的申请,先来看下谁生成的GraphicBufferAlloc实例。
BufferQueueCore::BufferQueueCore(const sp<IGraphicBufferAlloc>& allocator) :
mAllocator(allocator)@BufferQueueCore.cpp{
if (allocator == NULL) {
//这里返回的 ISurfaceComposer类型的对象 composer,实际就是SurfaceFinger,最终 IGraphicBufferAlloc的实例生成还是由SurfaceFinger来完成的。 ComposerService类是SurfaceComposerClient.cpp的内部类。
sp<ISurfaceComposer> composer(ComposerService::getComposerService());
mAllocator = composer->createGraphicBufferAlloc();
}
}
可以看到这里创建的是一个GraphicBufferAlloc对象。
sp<IGraphicBufferAlloc> SurfaceFlinger::createGraphicBufferAlloc()@SurfaceFlinger.cpp
{
sp<GraphicBufferAlloc> gba(new GraphicBufferAlloc());
return gba;
}
在BufferQueueCore的初始化列表中虽然给IGraphicBufferAlloc做了赋值:mAllocator(allocator),但实际这个值是null的,因为它是由BufferQueue.cpp的默认参数传过来的,而这默认参数初始值是null的,所以需要在构造函数中重新生成IGraphicBufferAlloc实例。
BufferQueueCore中有一个重要的成员数组BufferQueueDefs::SlotsTypemSlots;
前面在说的surface中也有一个同名的成员数组BufferSlotmSlots[NUM_BUFFER_SLOTS];都是BufferSlot类型,只是定义有差别。
这是Surface中的BufferSlot的定义,是一个结构体。
Surface.h
struct BufferSlot {
sp<GraphicBuffer> buffer;
Region dirtyRegion;
};
BufferSlot mSlots[NUM_BUFFER_SLOTS];
下面是BufferQueueCore中的Bufferslot中的定义:
BufferSlot.h
struct BufferSlot {
// mGraphicBuffer指向一个slot所分配的buffer,如果buffer还没分配,值为null。
sp<GraphicBuffer> mGraphicBuffer;
//标示一个buffer slot的当前状态。
BufferState mBufferState;
}
一个buffer可以有5中状态。
struct BufferState {
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表明缓冲区当前可用,可以被生产者dequeued,这个slots的owner是BufferQueue,当dequeueBuffer后会转变为DEQUEUED。
DEQUEUED表明这个buffer已经被生产者dequeued,但是还没被queued或者canceled,生产者可以修改这个buffer的内容,现在buffer的owner是producer(应用程序),可以通过调用queueBuffer或attachBuffer转成QUEUED,也可以通过调用cancelBuffer或detachBuffer转成FREE。
QUEUED表明这个buffer已经被Producer填充了数据,可以被consumer使用,现在buffer的owner是BufferQueue,可以通过调用acquireBuffer转成ACQUIRED,
ACQUIRED表明这个buffer已经被consumeracquired了,现在的owner是consumer,通过releasebuffer可以转成FREE。
SHARED表明这个buffer被用于sharedbuffer mode。在同一时间,它可以是除FREE外的其他的状态的集合。
}
通过上面buffer的各个状态的介绍,对buffer的管理主要有BufferQueue,Producer,Consumer,三个对象。BufferQueue的实现者就是BufferQueueCore,它是一个中心,Producer想要获取一个buffer,是通过BufferQueueCore完成的,同样的当有一个buffer可以被consumer消费时,也是通过BufferQueueCore来通知到到consumer的。
Producer通常是指应用程序,应用程序不断刷新UI,把产生的显示数据写到buffer中,当Producer需要一块buffer时,先向bufferQueue发起dequeue申请,然后才能对制定的缓冲区进行填充操作,当填充完成后,通过调用queueBuffer把这个buffer入队到Bufferqueue中,由BufferQueuecore通知consumer有可以别消费的buffer了。
具体怎么通知到consumer的,还要介绍一个类ConsumerListener,介绍了这个类的几个主要接口,就知道是怎么通知到consumer的了。
class ConsumerListener : public virtual RefBase {
//当一帧对消费者来说可用时就会调用这个函数,
virtual void onFrameAvailable(const BufferItem& item) = 0; /* Asynchronous */
//这个函数会去通知consumer,BufferQueue已经释放了一个或多个GraphicBuffers的引用,consumer应该调用getReleasedBuffers去检索这个buffer列表。
virtual void onBuffersReleased() = 0;
}
2),BufferQueue缓冲区的分配。
分析缓冲区的分配,就是分析BufferSlot数组中的指针mGraphicBuffer的空间分配。这个指针一开始是null,下面看什么情况下为mSlots数组中的一个slot分配实际空间。
整个需求的起点是Producer对buffer的dequeueBuffer,所以从分析这个函数开始:
BufferQueueProducer.cpp
status_t BufferQueueProducer::dequeueBuffer(int *outSlot,sp<android::Fence> *outFence,
uint32_t width,uint32_t height, QueueBufferOutput *output) @BufferQueueProducer.cpp{
//step1,这个while循环,查找一个可用的slot,具体是通过 waitForFreeSlotThenRelock函数实现,也就是found的有效值。
int found = BufferItem::INVALID_BUFFER_SLOT;
while (found == BufferItem::INVALID_BUFFER_SLOT) {
status_t status = waitForFreeSlotThenRelock(FreeSlotCaller::Dequeue,&found);
//如果不允许分配新的buffers, waitForFreeSlotThenRelock还必须返回一个包含buffer的slot,如果这个buffer需要充分配才能满足要求,就要先把它free了,然后尝试再获取一个。
const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
if (!mCore->mAllowAllocation) {
if (buffer->needsReallocation(width, height, format, usage)) {
mCore->mFreeSlots.insert(found);
mCore->clearBufferSlotLocked(found);
found = BufferItem::INVALID_BUFFER_SLOT;
continue;
}
}
}
//step2,成功找到slot序号,接下来对这个bufferslot对象做初始化。还要判断要不要为这个slot重新分配空间。
*outSlot = found;
mSlots[found].mBufferState.dequeue();
if ((buffer == NULL) ||
buffer->needsReallocation(width, height, format, usage)){
mSlots[found].mAcquireCalled = false;
mSlots[found].mGraphicBuffer = NULL;
mSlots[found].mFence = Fence::NO_FENCE;
mCore->mIsAllocating = true;
returnFlags |= BUFFER_NEEDS_REALLOCATION;
}
//step3,上一步的判断结果需要重新分配空间,调用 createGraphicBuffer分配空间。
if (returnFlags & BUFFER_NEEDS_REALLOCATION) {
sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
width, height, format, usage,{mConsumerName.string(),
mConsumerName.size()} , &error));
//分配的空间,赋值给了slot,这里的mSlots实质是BufferQueueCore中的变量。
mSlots[*outSlot].mGraphicBuffer = graphicBuffer;
}
}
对其中关键步骤做详细分析:
step1,怎么找到一个可用的slot。found指的是这个Bufferslot在mSlots数组中的序号。
status_t BufferQueueProducer::waitForFreeSlotThenRelock(
FreeSlotCaller caller,int* found) const {
bool tryAgain = true;
while (tryAgain) {
// mActiveBuffers这个集合中包含所有非free的buffer。然后分别统计dequeued的个数,acquired的个数。
for (int s : mCore->mActiveBuffers) {
if (mSlots[s].mBufferState.isDequeued()) {
++dequeuedCount;
}
if (mSlots[s].mBufferState.isAcquired()) {
++acquiredCount;
}
}
//不允许Producersdequeue的数量的超过 mMaxDequeuedBufferCount,这个判断只在buffer已经被queued的情况下。 mMaxDequeuedBufferCount是Producer一次可以dequeue的buffers的数量,默认是1,可以通过setMaxDequeuedBufferCount来修改。
if (mCore->mBufferHasBeenQueued &&
dequeuedCount >= mCore->mMaxDequeuedBufferCount) {
return INVALID_OPERATION;
}
//如果在shared buffer mode,并且有一个shared buffer存在,就返回这个slot。
if (mCore->mSharedBufferMode && mCore->mSharedBufferSlot !=
BufferQueueCore::INVALID_BUFFER_SLOT) {
*found = mCore->mSharedBufferSlot;
}else {
//slot的获取,主要来自两个集合,mFreeSlots和mFreeBuffers,
//mFreeSlots包含的是所有状态是free,并且没有attached的slots,
//mFreeBuffers包含所有状态是free,但是已经attached的slots。
if (caller == FreeSlotCaller::Dequeue) {
//如果调用来自与dequeue,优先选择mFreeBuffers中的。
int slot = getFreeBufferLocked();
if (slot != BufferQueueCore::INVALID_BUFFER_SLOT) {
*found = slot;
}else{
*found = getFreeSlotLocked();
}
}else{
//如果调用来自于attache,优先选择mFreeSlots中的。
int slot = getFreeSlotLocked();
if (slot != BufferQueueCore::INVALID_BUFFER_SLOT) {
*found = slot;
}else{
*found = getFreeBufferLocked();
}
}
}
//如果没有找到符合要求的buffer,或者queue的buffers还有太多没有完成,就要等待这个buffer被acquired或者released,或者修改最大的buffer数量。这里使用条件变量mDequeueCondition进入wait,当有buffer被释放时,这个条件就会满足,然后继续查找。
if (tryAgain) {
mCore->mDequeueCondition.wait(mCore->mMutex);
}
}//while(tryAgain)
return NO_ERROR;
}
Step2,找到可用的slot,还要判断是否要重新分配空间,即needsReallocation,如果buffer的属性跟要求的属性不符(主要指宽,高,格式,usage),就要重新分配,最后的返回值会加上returnFlags|= BUFFER_NEEDS_REALLOCATION;标记。
Step3,调用IGraphicBufferAlloc的方法createGraphicBuffer方法分配GraphicBuffer。IGraphicBufferAlloc对应的服务端的实现是GraphicBufferAlloc.cpp,所以这个方法的实现就到了GraphicBufferAlloc.cpp中,这里new了一个GraphicBuffer,这个GraphicBuffer会赋值给BufferQueueCore中的变量mSlots中的slot的mGraphicBuffer。
sp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t width,
uint32_t height, PixelFormat format, uint32_t usage,
std::string requestorName, status_t* error) @GraphicBufferAlloc.cpp{
sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(
width, height, format, usage, std::move(requestorName)));
status_t err = graphicBuffer->initCheck();
*error = err;
if (err != 0 || graphicBuffer->handle == 0) {
if (err == NO_MEMORY) {
GraphicBuffer::dumpAllocationsToSystemLog();
}
return 0;
}
return graphicBuffer;
}
BufferQueueProducer.cpp中的dequeueBuffer的源头是在surface中调用的dequeueBuffer,所以BufferQueueProducer.cpp这边执行完会返回到Surface.cpp中,
int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) @Surface.cpp{
//BufferQueueProducer.cpp的dequeueBuffer是从这里开始的。
status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence,
reqWidth, reqHeight, reqFormat, reqUsage);
//如果返回值带有BUFFER_NEEDS_REALLOCATION,还要调用 requestBuffer。
if ((result & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) || gbuf == 0) {
result = mGraphicBufferProducer->requestBuffer(buf, &gbuf);
}
}
调用requestBuffer是获取最新的buffer地址,BufferQueueProducer中分配的buffer是在服务端进程空间的,而surface需要的buffer是要在客户端进程,也就是应用进程空间使用的,这两块buffer应该指向同一块物理内存,怎么实现让两块buffer指向同一块物理内存的,这就是requestbuffer的作用。
//这个方法是BpGraphicBufferProducer中的方法:
virtual status_t requestBuffer(int bufferIdx, sp<GraphicBuffer>* buf) @IGraphicBufferProducer.cpp{
Parcel data, reply;
//只传了在mSlots中的序号 bufferIdx,第二个参数* buf实际是一个出参。
data.writeInt32(bufferIdx);
//开始跨进程操作。
status_t result =remote()->transact(REQUEST_BUFFER, data, &reply);
//读取服务端返回的信息,在执行跨进程操作时,client端会被挂起,等服务端处理完成返回结果时,在唤醒client继续执行。
bool nonNull = reply.readInt32();
if (nonNull) {
//这里生成一个GraphicBuffer实例,实际是一个空壳,要通过服务端的返回值来填充。
*buf = new GraphicBuffer();
//使用服务端的返回的结果填充**buf ,这个**buf具体指的什么?从surface.cpp传入的参数说起:
//sp<GraphicBuffer>& gbuf(mSlots[buf].buffer);这个gbuf 是一个指向 mSlots[buf].buffer的引用,//传入requestBuffer中的实参是&gbuf,也就是说*buf指针指向的是 gbuf 的地址,所以**buf指向的就是 gbuf代表的内容,也就是 mSlots[buf].buffer。
result = reply.read(**buf);
}
result = reply.readInt32();
}
相应client请求的代码如下:
status_t BnGraphicBufferProducer::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags){
switch(code) {
//匹配请求的业务码 REQUEST_BUFFER。
case REQUEST_BUFFER: {
//读取要处理的slot序号。
int bufferIdx = data.readInt32();
sp<GraphicBuffer> buffer;
int result = requestBuffer(bufferIdx, &buffer);
//写入本地端是否成功获取到了对应的GraphicBuffer,这个GraphicBuffer就是dequeuebuffer中申请//的,也即是BufferQueueCore中的mSlots[slot].mGraphicBuffer。
reply->writeInt32(buffer != 0);
if (buffer != 0) {
//把 mGraphicBuffer写入reply,等待客户端读取。
reply->write(*buffer);
}
reply->writeInt32(result);
return NO_ERROR;
}
}
}
上面的实现中,清晰的描述了一个怎样跨进程传递一个对象。
能够通过Binder跨进程传递的对象,在java层的通常要继承Parcelable,如Bundle.java,需要实现的接口是writeToParcel,readFromParcel;
在native层通常要继承Flattenable,如这里的GraphicBuffer.cpp,需要实现的接口是flatten,unflatten。
只要看下GraphicBuffer的flatten,unflatten的函数实现,就可以清楚客户端、服务端的两块buffer是不是指向的同一块物理空间了。
status_t GraphicBuffer::flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const @GraphicBuffer.cpp{
int32_t* buf = static_cast<int32_t*>(buffer);
//handle的类型是buffer_handle_t* handle,它是在生成GraphicBuffer实例时,//由GraphicBufferAllocator在申请真实的物理内存时赋值的,代表了代表了一块共享缓冲区的句柄。
if (handle) {
//写入缓冲区相关的数据,client端也会按相同的格式读取。
buf[9] = handle->numFds;
buf[10] = handle->numInts;
memcpy(fds, handle->data,
static_cast<size_t>(handle->numFds) * sizeof(int));
memcpy(&buf[11], handle->data + handle->numFds,
static_cast<size_t>(handle->numInts) * sizeof(int));
}
}
status_t GraphicBuffer::unflatten(void const*& buffer, size_t& size,
int const*& fds, size_t& count) @GraphicBuffer.cpp{
const size_t numFds = static_cast<size_t>(buf[9]);
const size_t numInts = static_cast<size_t>(buf[10]);
if (numFds || numInts) {
//通过生成一个本地层 native_handle实例,把相关的数据复制过来。这块物理空间跟BufferQueueCore中指向的物理空间是一致的。这就实现了client和服务端之间缓冲区的共享。
native_handle* h = native_handle_create(
static_cast<int>(numFds), static_cast<int>(numInts));
memcpy(h->data, fds, numFds * sizeof(int));
memcpy(h->data + numFds, &buf[11], numInts * sizeof(int));
}
}
在surface执行dequeuebuffer的过程中,如果需要重新分配空间,就要调用requestbuffer就是来更新client端mSlots中相应的缓冲区信息的。这样就保证了Surface和bufferQueuecore之前在数据缓冲区上的一致。
3)应用程序跟BufferQueue的关系。
应用程序不会直接使用BufferQueue,接下来分析应用程序跟bufferQueue之间怎么配合完成图形绘制的。
分析这个过程需要一个切入点,可以从一个常见的应用程序的启动入手,经过ViewrootImpl.java的setView,到WindowManagerService.java的relayoutWindow,然后转到createSurface的分析。这个过程要从java层进过jni到本地层相对繁琐,不利于直观跟BufferQueue的关系。所以借助系统的一段本地层的测试代码来分析,为什么要用这段代码?我们知道surfaceflinger是借助于opengles来完成绘图的,很多应用程序也是借助于opengles来完成UI显示的,比如图库的图片展示,相机的预览界面等,当然也有应用程序是借助于skia这个图形库。下面这段代码不仅展示了应用程序跟BufferQueue的通信过程,还展示了opengles和egl的使用流程。
frameworks/native/libs/gui/tests/GLTest.cpp
void GLTest::SetUp() {
//获取默认的物理屏幕。
mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
//初始化。
eglInitialize(mEglDisplay, &majorVersion, &minorVersion);
//选取最佳的config。
eglChooseConfig(mEglDisplay, getConfigAttribs(), &mGlConfig, 1, &numConfigs);
//生成一个SurfaceComposerClient实例,它是应用程序与surfaceflinger之间的通信桥梁,不过SurfaceComposerClient只是一个封装,实质是通过内部的ISurfaceComposerClient来执行的,ISurfaceComposerClient对应的服务端实现是Client。
mComposerClient = new SurfaceComposerClient;
mComposerClient→initCheck();
//生成一个surface,surface是由surfaceControl来管理的,所以这里返回的是SurfaceControl。
mSurfaceControl = mComposerClient->createSurface(String8("Test Surface"),
getSurfaceWidth(), getSurfaceHeight(),PIXEL_FORMAT_RGB_888, 0);
//设置layer的层级,层级越大越靠近用户。
mSurfaceControl->setLayer(0x7FFFFFFF);
mSurfaceControl→show();
//从surfacecontrol中取出surface,得到了egl需要的本地窗口。
sp<ANativeWindow> window = mSurfaceControl→getSurface();
//通过本地窗口window创建surface。
mEglSurface = createWindowSurface(mEglDisplay, mGlConfig, window);
//创建、设置当前context环境。
mEglContext = eglCreateContext(mEglDisplay, mGlConfig, EGL_NO_CONTEXT,
getContextAttribs());
eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,mEglContext));
}
SurfaceComposerClient是一个封装,具体功能实现是通过其内部的ISurfaceComposerClient来实现的,而ISurfaceComposerClient对应服务端的实现是Client.cpp,所以上面的createSurface的实现就在Client中。这里涉及ipc,具体细节就不列出代码了。
SurfaceComposerClient.cpp
sp<SurfaceControl> SurfaceComposerClient::createSurface(const String8& name,uint32_t w,
uint32_t h,PixelFormat format,uint32_t flags)@SurfaceComposerClient.cpp{
sp<IBinder> handle;
sp<IGraphicBufferProducer> gbp;
//调用服务端的实现,实质是创建了一个layer,通过这个layer获取 IGraphicBufferProducer。
status_t err = mClient->createSurface(name, w, h, format, flags,&handle, &gbp);
//生成一个 SurfaceControl,由他管理surface。
sur = new SurfaceControl(this, handle, gbp);
return sur;
}
接着看服务端的实现,createSurface这个方法只能在GL线程中调用,这样它才能范文GL的上下文环境。
Client.cpp
status_t Client::createSurface(const String8& name,uint32_t w, uint32_t h,
PixelFormat format, uint32_t flags,sp<IBinder>* handle,sp<IGraphicBufferProducer>* gbp){
class MessageCreateLayer : public MessageBase {
SurfaceFlinger* flinger;
//这个client表明,这个消息来自于那个client,
Client* client;
//与这个layer对应的handle和gbp。
sp<IBinder>* handle;
sp<IGraphicBufferProducer>* gbp;
status_t result;
const String8& name;
uint32_t w, h;
PixelFormat format;
uint32_t flags;
virtual bool handler() {
//这里是由surfaceFlinger来执行操作。
result = flinger->createLayer(name, client, w, h, format, flags,handle, gbp);
return true;
}
}
//把请求通过一个同步函数把msg放入队列,等到有结果再返回。
sp<MessageBase> msg = new MessageCreateLayer(mFlinger.get(),
name, this, w, h, format, flags, handle, gbp);
mFlinger->postMessageSync(msg);
return static_cast<MessageCreateLayer*>( msg.get() )->getResult();
}
SurfaceFlinger.cpp
status_t SurfaceFlinger::createLayer(const String8& name,const sp<Client>& client,
uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp)@SurfaceFlinger.cpp{
sp<Layer> layer;
switch (flags & ISurfaceComposerClient::eFXSurfaceMask) {
//根据flag,创建不同的layer,这里是创建普通的layer,代表了一个画面。
case IsurfaceComposerClient::eFXSurfaceNormal:
result = createNormalLayer(client,name, w, h, flags, format,
handle, gbp, &layer);
break;
}
//将layer,gbp添加到全局的管理中。
result = addClientLayer(client, *handle, *gbp, layer);
}
SurfaceFlinger.cpp
status_t SurfaceFlinger::createNormalLayer(const sp<Client>& client,
const String8& name, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format,
sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer)@SurfaceFlinger.cpp{
//创建一个layer,同时给他设置缓冲区。
*outLayer = new Layer(this, client, name, w, h, flags);
status_t err = (*outLayer)->setBuffers(w, h, format, flags);
//通过layer获取IGraphicBufferProducer。
*handle = (*outLayer)→getHandle();
*gbp = (*outLayer)->getProducer();
}
//addClientLayer函数的实现。
status_t SurfaceFlinger::addClientLayer(const sp<Client>& client,const sp<IBinder>& handle,
const sp<IGraphicBufferProducer>& gbc,const sp<Layer>& lbc)@SurfaceFlinger.cpp{
//把layer添加到当前state的列表中。把gbc添加到全局变量中。
mCurrentState.layersSortedByZ.add(lbc);
mGraphicBufferProducerList.add(IInterface::asBinder(gbc));
//让layer与client产生关联,也就是添加到client的mLayers成员变量中。
client->attachLayer(handle, lbc);
}
//再回头看下*handle= (*outLayer)→getHandle();其中的handle是什么类型,又起了什么作用呢?
Layer.cpp
//创建了一个handle对象,并传入的surfaceflinger。
sp<IBinder> Layer::getHandle() @Layer.cpp{
return new Handle(mFlinger, this);
}
//这个handle只是传给client端的一个BBbinder,当客户端释放了这个引用时,会调用其析构函数,那么它的析构函数做了什么事情呢?Handle本身没写析构函数,所以要做的事情就在其父类LayerCleaner的析构函数中。
class Layer::Handle : public BBinder, public LayerCleaner {
Handle(const sp<SurfaceFlinger>& flinger, const sp<Layer>& layer)
: LayerCleaner(flinger, layer), owner(layer) {}
};
//LayerCleaner的析构函数,调用了surfaceflinger的onLayerDestroyed,把layer从surfaceflinger的全局变量mCurrentState.layersSortedByZ中移除。
Layer::LayerCleaner::~LayerCleaner() {
mFlinger->onLayerDestroyed(mLayer);
}
//Layer中很多变量的实例化,都是在onFirstRef中完成的,当Layer实例第一次被引用时会执行onFirstRef函数。
Layer.cpp
void Layer::onFirstRef() {
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
//通过BufferQueue创建BufferQueueProducer,BufferQueueConsumer,这样标识了 IGraphicBufferProducer对应的服务端是BufferQueueProducer, IGraphicBufferConsumer对应的服务端是 BufferQueueConsumer,同时BufferQueueProducer、 BufferQueueConsumer的构造函数中都有一个BufferQueueCore实例,生成者,消费者的对缓冲区的操作都会经过BufferQueueCore。
BufferQueue::createBufferQueue(&producer, &consumer);
//这里返回给client端的并不是 IGraphicBufferProducer,而是对它的封装类 MonitoredProducer, //MonitoredProducer并没有增加新的功能,只是在 IGraphicBufferProducer被销毁时,通知
// Surfaceflinger做些操作。
mProducer = new MonitoredProducer(producer, mFlinger);
mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(consumer, mTextureName,this);
}
//我们只关注MonitoredProducer的构造函数,看在IGraphicBufferProducer被销毁时,它要做什么。
MonitoredProducer.cpp
MonitoredProducer::~MonitoredProducer() @MonitoredProducer.cpp{
//这里使用了跟Client.cpp中调用surfaceflinger创建layer类似的方式,不同的是这里是异步的消息机制。
class MessageCleanUpList : public MessageBase {
virtual bool handler() {
//把IGraphicBufferProducer从surfaceflinger的列表中删除,这个操作是异步执行的,因为不知道会从哪里调用这个析构函数。还记得 mProducer是什么时候添加到这个列表中的吗?是在surfaceflinger的createLayer中,当创建一个layer之后,调用addClientLayer来添加的。
mFlinger->mGraphicBufferProducerList.remove(mProducer);
}
}
mFlinger->postMessageAsync(new MessageCleanUpList(mFlinger, asBinder(this)));
}
在Layer中还有一个重要的变量SurfaceFlingerConsumer。
SurfaceFlingerConsumer是GLConsumer的简单的包装类,把IGraphicBufferConsumer实例传给了GLConsumer。
SurfaceFlingerConsumer.cpp
class SurfaceFlingerConsumer : public GLConsumer {
SurfaceFlingerConsumer(const sp<IGraphicBufferConsumer>& consumer,
uint32_t tex, const Layer* layer)
: GLConsumer(consumer, tex, GLConsumer::TEXTURE_EXTERNAL, false, false),
mPrevReleaseFence(Fence::NO_FENCE), mLayer(layer){}
}
class GLConsumer :public ConsumerBase {}
class ConsumerBase :public virtual RefBase,protected ConsumerListener {}
GLConsumer有继承自ConsumerBase,间接继承了ConsumerListener。
接下来逐层分析逐个继承关系。
GLConsumer会消费来自BufferQueue的缓冲区或者叫图形数据,并把他们转做texture为opengl使用。一个典型的使用方式是使用所需要的选项设置GLConsumer,然后当有一帧需要时,调用updateTexImage,这个函数会获取最近queued的buffer,然后绑定这个buffer到GLtexture,如果这一帧是可用的,texture会被更新,如果不可用,前一帧的内容会被保留。
ConsumerBase是BufferQueue消费者的基类,它处理一些通用任务,比如到BufferQueue的连接,buffer池的管理,其中的成员变量sp<IGraphicBufferConsumer>mConsumer;就是SurfaceFlingerConsumer传过来的,ConsumerBase是通过IGraphicBufferConsumer对象来对BufferQueue执行操作的。
简单做个总结:
1)应用程序通过BufferQueue执行绘图,surfaceflinger会把系统中所有应用程序最终的绘图结果进行混合,然后送到物理屏幕显示。应用程序跟surfaceflinger之间的通信桥梁是IsurfaceComposrClient。
这个类被封装在SurfaceComposerClient中。
2)应用程序通过SurfaceComposerClient调用CreateSurface的过程中,除了得到IGraphicBufferProducer实例外,还创建了一个layer。把控制这个layer的handle,IGraphicBufferProducer对象,连同SurfaceComposerClient自身都保存在应用端的Surfacecontrol中。
3)Surface,应用程序通过Surfacecontrol的getSurface获取,其内部持有IGraphicBufferProducer对象,即BufferQueueProducer的实现接口。如果egl想通过Surface这个本地窗口完成某个功能,Surface实际上是利用IGraphicBufferProducer取得远程端的服务,完成egl的请求。
4)应用程序跟layer应该是一对多的关系,因为createSurface是可以被调用多次的,并且,一个应用程序申请的多个layer可以通过addClientLayer添加到一个全局变量mLayers中。应用程序申请的layer,一方面要记录都各个Client的内部变量mLayers中,另一方面还要告知SurfaceFlinger,这个操作也是在addClientLayer函数中完成的,即把layer添加到全局变量mCurrentState.layerSortByZ,Surfaceflinger会对这个列表中的所有layer排序,排序的结果直接影响了屏幕显示的画面。
5)每个layer对应一个BufferQueue,所以一个应用程序可能对应多个BufferQueue。layer并没有直接持有BufferQueue对象,而是通过其内部的IGraphicBufferProducer,mSurfaceFlingerConsumer来管理。