文章都是通过阅读源码分析出来的,还在不断完善与改进中,其中难免有些地方理解得不对,欢迎大家批评指正。 1.1.1 应用程序与BufferQueue的关系接着上一小节未解决完的问题继续讲解。 现在我们已经明白了应用程序利用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的对应关系 |
|
来自: 老匹夫 > 《Graphics》