文章都是通过阅读源码分析出来的,还在不断完善与改进中,其中难免有些地方理解得不对,欢迎大家批评指正。
转载请注明:From LXS. http://blog.csdn.net/uiop78uiop78/
GUI系统之SurfaceFlinger章节目录:
blog.csdn.net/uiop78uiop78/article/details/8954508
接着上一小节未解决完的问题继续讲解。
现在我们已经明白了应用程序利用SurfaceFlinger进行绘制工作的大致流程了,只不过在这个过程中直到最后才出现了BufferQueue。应用程序具体是如何借助BufferQueue来完成工作的呢?
仔细观察不难发现,当应用端通过ISurfaceComposerClient::createSurface()来发起创建Surface的请求时,SurfaceFlinger服务进程这边会创建一个Layer。既然Layer代表了一个画面图层,那么它肯定需要有存储图层数据的地方,因而我们选择从这里做为入口。
/*frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp*/
/*应用程序首先是要通过ISurfaceComposerClient来访问createSurface,这个接口实际上只是一个中介,它将应用的请求传送到SurfaceFlinger的消息队列中,而不是直接调用SurfaceFlinger来处理。这样做是有必要的,因为一个系统中需要SurfaceFlinger处理的来自各应用程序的消息是很多的,除非一些紧急情况,否则都应该排队等待*/
sp<ISurface>SurfaceFlinger::createSurface(ISurfaceComposerClient::surface_data_t* params,
constString8& name, const sp<Client>& client, DisplayID d,
uint32_tw, uint32_t h, PixelFormat format, uint32_t flags)
{
sp<LayerBaseClient>layer;
sp<ISurface>surfaceHandle;
…
sp<Layer>normalLayer;
switch (flags &eFXSurfaceMask) { //Layer类型
case eFXSurfaceNormal:
normalLayer = createNormalSurface(client, d, w, h, flags, format);
layer =normalLayer;
break;
case eFXSurfaceBlur://4.1系统中将Blur与Dim类型当成一种
case eFXSurfaceDim:
layer = createDimSurface(client, d, w, h, flags);
break;
case eFXSurfaceScreenshot:
layer = createScreenshotSurface(client, d, w, h, flags);
break;
}
if (layer != 0) {…
surfaceHandle = layer->getSurface();
…
}
return surfaceHandle;
}
可以看到,最后返回给应用程序的ISurface对应的变量是surfaceHandle,由layer通过getSurface()产生。从enum值定义来看,当前系统中有多达十几种Layer类型,只不过多数还没有真正实现,目前能用的只有四个,即eFXSurfaceNormal、eFXSurfaceBlur、eFXSurfaceDim、eFXSurfaceScreenshot。第一种就是通常情况下的图层;第二和第三种在当前系统中都被以eFXSurfaceDim来实现,从注释上看,很可能是Blur类型的Layer比较耗资源,所以暂时用Dim来取代。相信在后续的Android版本中还会把它们再区分开来。
Layer和ISurface有什么联系?
图 11?18 Layer类继承关系
/*frameworks/native/services/surfaceflinger/LayerBase.cpp*/
sp<ISurface> LayerBaseClient::getSurface()
{
sp<ISurface> s;
Mutex::Autolock _l(mLock);
LOG_ALWAYS_FATAL_IF(mHasSurface, "LayerBaseClient::getSurface() hasalready been called");
mHasSurface = true;
s = createSurface(); //通过这个函数产生一个ISurface
mClientSurfaceBinder= s->asBinder();
return s;
}
这个函数只能被调用一次,由mHasSurface来控制。当被第二次调用时,就会发生assert错误。LayerBaseClient通过成员变量mClientSurfaceBinder来记录ISurface。一个系统中同时存在的Layer和Surface通常不会只有一个,那么ISurface是如何知道它所属的Layer的呢?
sp<ISurface> LayerBaseClient::createSurface()
{
class BSurface : publicBnSurface, public LayerCleaner {
virtualsp<ISurfaceTexture> getSurfaceTexture() const { return 0; }
public:
BSurface(constsp<SurfaceFlinger>& flinger, const sp<LayerBaseClient>&layer)
:LayerCleaner(flinger, layer) { }
};
sp<ISurface> sur(newBSurface(mFlinger, this));
return sur;
}
和一般的写法不同,ISurface的本地实现BSurface是定义在函数中的。不过这不是问题的关键,关键问题是BSurface中的getSurfaceTexture居然直接返回了一个null(0),显然如果是这样的话程序就没法继续执行了。唯一的解释是应该有LayerBaseClient的子类重载实现了这一函数,来看下Layer中是不是这样的。
/*frameworks/native/services/surfaceflinger/Layer.cpp*/
sp<ISurface> Layer::createSurface()
{
class BSurface : publicBnSurface, public LayerCleaner {
wp<const Layer>mOwner;
virtualsp<ISurfaceTexture> getSurfaceTexture() const {
sp<ISurfaceTexture> res;
sp<constLayer> that( mOwner.promote() );
if (that != NULL){
res =that->mSurfaceTexture->getBufferQueue();
}
return res;
}
public:
BSurface(constsp<SurfaceFlinger>& flinger, const sp<Layer>& layer)
: LayerCleaner(flinger,layer), mOwner(layer) { }//mOwner在构造函数中以Layer赋值
};
sp<ISurface> sur(newBSurface(mFlinger, this));
return sur;
}
看来我们猜测的是对的,Layer的确重载了createSurface。而且这里的getSurfaceTexture就不是pseudo的了。函数的最后生成了一个BSurface,注意看下它的构造参数中传入了this指针,也就是Layer对象自身。这个指针是后期ISurface与它通信的关键。同时作为入参的还有mFlinger,这样ISurface也可以访问到SurfaceFlinger了。因为这几个类都运行于同一个进程空间中,可以看到它们都直接是内存地址的传递,不需要IPC通信。
当应用程序通过ISurfaceComposerClient::createSurface()得到一个ISurface后,它会接着使用ISurface::getSurfaceTexture()来取得可用的texture(具体是由Surface在构造时获取,然后再通过Surface::init->setISurfaceTexture来将ISurfaceTexture赋值给SurfaceTextureClient::mSurfaceTexture),这个ISurfaceTexture是应用程序中的opengl本地窗口SurfaceTextureClient实现ANativeWindow规定的“协议”的基础)。
在getSurfaceTexture中,mOwner是一个指向Layer对象的弱指针,that->mSurfaceTexture指的是Layer中的SurfaceTexture类成员变量,所以函数最终是通过SurfaceTexture::getBufferQueue()来获得ISurfaceTexture。更具体地过程是,当Layer第一次被引用时,在onFirstRef()中会对mSurfaceTexture赋值。因为ISurface(即BSurface)持有这个Layer对象(mOwner),所以当应用程序申请getSurfaceTexture时,它才能间接地向Layer要求取得ISurfaceTexture。我们前面说过,在binder server端,这个接口的实现类就是BufferQueue,如下所示:
/*frameworks/native/libs/gui/SurfaceTexture.cpp*/
sp<BufferQueue> SurfaceTexture::getBufferQueue() const {
Mutex::Autolocklock(mMutex);
return mBufferQueue;
}
函数直接返回了mBufferQueue,因为这个成员变量在SurfaceTexture构造时就已经初始化过了,它指向一个BufferQueue对象。大家一定要记住,ISurfaceTexture的server端实现是BufferQueue,由于命名上的差异,这点很容易搞错。
这样应用程序与BufferQueue的关系就比较明朗了。虽然中间经历了多次跨进程通信,但对于应用程序来说最终只使用到了BufferQueue(通过ISurfaceTexture)。从本小节的内容中,我们也可以从侧面证明如下几个关键点:
(1) 应用程序可以调用createSurface来建立多个Layer,它们是一对多的关系。理由就是createSurface中没有任何机制来限制应用程序的多次调用,相反,它会把一个应用程序多次申请而产生的Layer统一管理,如下:
sp<ISurface> SurfaceFlinger::createSurface(…constsp<Client>& client)
{
sp<LayerBaseClient>layer;
… /*省略的这部分是生成layer的过程,前面已经分析过了*/
if (layer != 0) {…
ssize_t token = addClientLayer(client,layer);//将client与layer记录起来
surfaceHandle =layer->getSurface();
if (surfaceHandle !=0) {…
if (normalLayer !=0) {//只对normal layer生效
Mutex::Autolock _l(mStateLock);
mLayerMap.add(layer->getSurfaceBinder(), normalLayer);
}
}…
}
为应用程序申请的layer,一方面需要告知SurfaceFlinger,另一方面也要记录到各Client内部中,这两个步骤是由addClientLayer()分别调用Client::attachLayer()和SurfaceFlinger::addLayer_l()来完成的。对于SurfaceFlinger,它需要对系统中当前所有的Layer进行Z-order排序,以决定用户所能看到的“画面”是什么样的。对于Client,它则利用内部的mLayers成员变量来一一记录新增(attachLayer)和移除(detachLayer)的图层。
(2) 每个Layer对应一个BufferQueue,换句话说,一个应用程序可能对应多个BufferQueue。Layer没有直接持有BufferQueue,而是由其内部的mSurfaceTexture来管理。
我们以下面这个关系图来结束本小节的学习:
图 11?19 应用程序与BufferQueue的对应关系
联系客服