接下来看下BufferQueue的申请分配,就是经典的生产者-消费者模型。
1)BufferQueueCore
可以认为BufferQueueCore是一个服务中心,生产者、消费者都要通过它来管理buffer。里面有一个重要的成员数组:BufferQueueDefs::SlotsType mSlots;这个BufferSlot中有一个成员变量:sp
FREE:buffer当前可用,可以被生产者dequeued,此时owner是BufferQueueCore,当dequeuebuffer调用时,状态可以转为dequeued。
DEQUEUED:buffer已经被dequeued,还没被queue或canceld,此时owner是producer。
QUEUED:buffer已经被生产者填充,并被queued,此时的owner是bufferQueueCore。
ACQUIRED:buffer已经被消费者获得,此时的owner是consumer。
SHARED:可以认为是除FREE外的其他状态的联合体,可以被多次dequeued,queued,acquired
一块buffer的生命周期依次是:FREEà DEQUEUEDà QUEUEDà ACQUIREDà FREE。
2)BufferQueueProducer
生产者就是填充buffer数据的人,通常是应用程序不断刷新UI,将数据写到buffer中。档producer需要一块buffer时,会先向BufferQuueuCore发起dequeue申请,然后对申请到的buffer操作,档数据写完后,调用queue接口,把buffer归还到bufferqueue的队列中。
3)BufferQueueConsumer
当一块buffer就绪后,消费者就开始工作了,consumer对buffer的处理是被动的,它必须要等到一块buffer填充好才能工作,那consumer怎么知道一块buffer已经填充好了?这里提供了另外一个类ConsumerListener,
class ConsumerListener : public virtualRefBase {
//两个纯虚函数,当一块buffer可以被消费时,onFrameAvailable会被调用,当BufferQueue通知consumer它已经释放其mSlot中的一个或多个GraphicBuffer的引用时,会调用onBuffersReleased。
virtualvoid onFrameAvailable(const BufferItem& item) = 0;
virtualvoid onBuffersReleased() = 0;
}
什么时候注册的这个ConsumerListener监听呢?这样看具体的使用consumer的代码场景。下面以SurfaceFlinger为例,它是由framebufferSurface间接操作buffer的consumer对象,
void SurfaceFlinger::init() @SurfaceFlinger_hwc1.cpp{
//这里通过BufferQueue::createBufferQueue,创建了BufferQueueCore实例,BufferQueueProducer实例,BufferQueueConsumer实例,并且BufferQueueCore作为后两者的参数,这样producer、consumer就跟服务中心建立了联系。
sp
BufferQueue::createBufferQueue(&producer,&consumer, new GraphicBufferAlloc());
//接着把consumer作为参数,创建FramebufferSurface实例
sp
}
看继承关系:FramebufferSurface继承了ConsumerBase
class FramebufferSurface : publicConsumerBase,…
所以在调用FramebufferSurface的构造函数时,也会调用父类ConsumerBase的构造函数,并且把consumer作为参数也传给了父类ConsumerBase,
FramebufferSurface::FramebufferSurface(HWComposer&hwc, int disp,
constsp
ConsumerBase(consumer),…
那么接着看ConsumerBase(consumer)的处理:
/* ConsumerBase.cpp */
ConsumerBase::ConsumerBase(constsp
boolcontrolledByApp) :
mConsumer(bufferQueue){
//创建消费者监听类对象
wp
sp
//connect连接,经过层层调用,把listener监听注册到bufferQueuecore中,
这样bufferQueuecore就可以利用这个监听通知到具体的消费者
status_t err =mConsumer->consumerConnect(proxy, controlledByApp);
BufferQueueConsumer::[email protected]à
mCore->mConsumerListener =consumerListener;//这里把consumerListener注册到服务者类bufferQueuecore中)
}
这样就清楚了buffer的生产者,消费者,管理者之间的关系。
接着真正开始看下bufferqueuecore中缓冲区的分配:
前面看到,bufferqueuecore中mSlots数组管理缓冲区,最大容量是64,这个mSlots一开始静态分配了64个bufferslot大小的空间,但是其中的数据缓冲区不是一次性分配的,不然就太浪费空间了,所以缓冲区的空间分配是动态的,具体就是producer在dequeuebuffer时,如果没有获取到可用的缓冲区,那就要重新分配空间了。
还接着前面分析的Surface,这个应用程序段的本地窗口要要向上层提供绘制图像的画板,即GraphicBuffer,那么它是怎么申请buffer的?这个过程很多的跨进程通信,
Surface::[email protected]{
//调用IGraphicBufferProducer.cpp的dequeueBuffer方法,这个类是Binder的客户端,对应服务端的实现是BufferQueueProducer.cpp,
status_tresult = mGraphicBufferProducer->dequeueBuffer(
&buf,&fence,reqWidth, reqHeight, reqFormat, reqUsage);
// BUFFER_NEEDS_REALLOCATION这个标记是native层传上来的,如果buffer需要重新分配空间,要调用requestBuffer,获取新buffer的地址,
if((result & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) || gbuf == 0){
result = mGraphicBufferProducer->requestBuffer(buf,&gbuf);}
}
详细看下dequeuebuffer的调用流程:
virtual status_t dequeueBuffer()@IGraphicBufferProducer.cpp{
//把请求传到服务端
status_tresult = remote()->transact(DEQUEUE_BUFFER, data, &reply);
}
status_t BnGraphicBufferProducer::onTransact()@IGraphicBufferProducer.cpp{
caseDEQUEUE_BUFFER: {
//转到服务端实现类中的dequeueBuffer
int result = dequeueBuffer(&buf,&fence, width, height, format, }
}
从继承关系可以看出BufferQueueProducer是IGraphicBufferProducer对应的server段:
class BufferQueueProducer : publicBnGraphicBufferProducer,…
这个函数很长,核心是查找一个符合要求的slot,对这个bufferslot做初始化,根据判断结果决定是否要重新分配空间
status_tBufferQueueProducer::dequeueBuffer( )@BufferQueueProducer.cpp{
//这个函数是获取一个slot,具体是getFreeBufferLocked或者getFreeSlotLocked,返回这个bufferslot在mSlots数组中的序号
BufferQueueProducer::waitForFreeSlotThenRelock(){
int slot = getFreeBufferLocked();
*found = getFreeSlotLocked(); }
//判断这个GraphicBuffer是否需要重新分配空间,判断条件就是buffer为空,因为它初始值是null,第一次使用它需要分配空间,如果不为null,但是buffer的width、height、format、usage属性跟要求的不一致,也要重新分配。
constsp
if((buffer == NULL) || buffer->needsReallocation(width, height, format,usage)){
//除了对bufferslot对象初始化之外,还要设置BUFFER_NEEDS_REALLOCATION这个标记,客户端surface在发现这个flag后,会调用requestBuffer获取新buffer的地址,这里客户端和buffer管理所处的服务端是分在两个进程的,这个buffer地址实际是匿名共享内存地址,这也是binder通信中的原理。
mSlots[found].mAcquireCalled= false;
mSlots[found].mGraphicBuffer= NULL;
mSlots[found].mRequestBufferCalled= false; …
returnFlags|= BUFFER_NEEDS_REALLOCATION;
}
//需要重新分配,调用BufferQueueCore中的GraphicBufferAlloc中函数createGraphicBuffer,生成一个newGraphicBuffer(width, height, format, usage, std::move(requestorName)));实例。
if(returnFlags & BUFFER_NEEDS_REALLOCATION) {
sp
width,height, format, usage,
{mConsumerName.string(), mConsumerName.size()}, &error));
}
}
到这里,客户端surface就完成了对buffer的申请。
前面分析performDraw,DrawSoftware时,在应用程序绘图结束,会将buffer解锁,会调用surface.unlockCanvasAndPost(canvas);提交给系统进行渲染,这个函数最终调用到surface.cpp中的函数:unlockAndPost
status_t Surface::unlockAndPost()@Surface.cpp{
//主要想看把这个buffer入队时,怎么样通知consumer来消费这个buffer的。
err= queueBuffer(mLockedBuffer.get(), fd); à
//接着调用到IGraphicBufferProducer中的queueBuffer方法,这里是通过binder实现的跨进程通信,IGraphicBufferProducer对应服务端的实现是BufferQueueProducer.cpp
status_terr = mGraphicBufferProducer->queueBuffer(i, input, &output);
}
status_t BufferQueueProducer::queueBuffer()@BufferQueueProducer.cpp{
//这里定义一个IConsumerListener,后面会执行具体的监听实例
sp
//把通过BufferQueueCore注册的IConsumerListener类的监听赋给frameAvailableListener
frameAvailableListener= mCore->mConsumerListener;
//调用onFrameAvailable通知消费者有已经渲染好的,可用的buffer,
frameAvailableListener->onFrameAvailable(item);
}
会监听FrameAvailable的有FramebufferSurface,还有layer.cpp。
void FramebufferSurface::onFrameAvailable()@FramebufferSurface.cpp{
//获取可用buffer
sp
sp
status_terr = nextBuffer(buf, acquireFence);
//在nextbuffer时,会调用acquireBuffer把这个buffer的状态置为acquire
status_terr = acquireBufferLocked(&item, 0);
//把这个buffer送到framebuffer中,也就是fb设备中,准备合成,送到屏幕显示
err= mHwc.fbPost(mDisplayType, acquireFence, buf);
}
以surfaceflinger这个consumer为例,SurfaceFlingerConsumer继承了FrameAvailableListener,而layer继承了SurfaceFlingerConsumer。
void Layer::onFrameAvailable(constBufferItem& item) {
}
总结下surface,surfaceflinger,bufferQueue,应用程序之间的联系。
一个应用程序是可以创建多个layer的,一个layer对应一个BufferQueue,一个BufferQueue中有多个GraphicBuffer,就是那个mSlots数组;可以认为surface在服务端对应的就是layer,一个客户端程序拥有的surface数量可能不止一个,通常一个activity下的UI布局共用一个surface进行绘图,一个activity对应一个viewtree,一个viewrootimpl,还记得app申请一个surface的起点就是viewrootimple的setview方法,一个app是可以有多个activity的。还有像surfaceview这类UI控件是独占一个surface进行绘制的,比如图库,camera,视频播放器都有surfaceview这类控件,所以他们的surface应该不止一个。
1)、ISurfaceComposerClient这个类是应用程序跟surfaceflinger间的通道,具体被封装在SurfaceComposerClient类中,通过surfaceflinger的createConnection方法获取,对应服务端的实现是Client.cpp
2)、IGraphicBufferProducer.cpp,这个类实例有应用程序创建Surface时得到,对于纯C++的应用程序来说,是通过sp
3)、Surface、从逻辑看,他是上面说的layer的使用者。从继承关系看,他是一个本地窗口,内部有IGraphicBufferProducer,当EGL想利用这个本地窗口surface完成一个功能时,surface实际上利用handle和IGraphicBufferProducer来获取远程服务端的服务,完成egl的请求。
值得一提的是c++层的应用程序创建surface是通过SurfaceComposerClient这个实例的方法来实现的;而java层的应用程序是通过SurfaceControl.cpp中的getSurface()返回了一个surface实例,并没有跟SurfaceComposerClient产生联系,所以真正跟Surfaceflinger间有联系的就是surface中的IGraphicBufferProducer,也就是它与BufferQueue有联系。