8.4.3 SurfaceControl分析
最后更新于:2022-04-02 05:52:31
1. SurfaceControl的来历
根据精简的流程可知,这一节要分析的是SurfaceControl对象。先回顾一下这个对象的创建过程,代码如下所示:
**android_view_Surface.cpp**
~~~
static void Surface_init(JNIEnv* env, jobjectclazz, jobject session,
jint pid, jstring jname, jint dpy, jint w, jint h, jint format, jintflags)
{
SurfaceComposerClient* client =
(SurfaceComposerClient*)env->GetIntField(session, sso.client);
//注意这个变量,类型是SurfaceControl,名字却叫surface,稍不留神就出错了。
spsurface;
if (jname == NULL) {
//调用Client的createSurface函数,得到一个SurfaceControl对象。
surface= client->createSurface(pid, dpy, w, h, format, flags);
}
......
//将这个SurfaceControl对象设置到Java层的对象中保存。
setSurfaceControl(env, clazz, surface);
}
~~~
通过上面的代码可知,SurfaceControl对象由createSurface得来,下面看看这个函数。
此时,读者或许会被代码中随意起的变量名搞糊涂,因为我的处理方法碰到了容易混淆的地方,尽量以对象类型来表示这个对象。
(1)分析createSurface的请求端
在createSurface内部会使用Binder通信将请求发给SF,所以它分为请求和响应两端,先看请求端,代码如下所示:
**SurfaceComposerClient.cpp**
~~~
spSurfaceComposerClient::createSurface(
int pid,
DisplayID display,//DisplayID是什么意思?
uint32_t w,
uint32_t h,
PixelFormat format,
uint32_t flags)
{
String8 name;
constsize_t SIZE = 128;
charbuffer[SIZE];
snprintf(buffer, SIZE, "", getpid());
name.append(buffer);
//调用另外一个createSurface,多一个name参数
returnSurfaceComposerClient::createSurface(pid, name, display,
w, h, format, flags);
}
~~~
在分析另外一个createSurface之前,应先介绍一下DisplayID的含义:
~~~
typedef int32_t DisplayID;
~~~
DisplayID是一个int整型,它的意义是屏幕编号,例如双屏手机就有内屏和外屏两块屏幕。由于目前Android的Surface系统只支持一块屏幕,所以这个变量的取值都是0。
再分析另外一个createSurface函数,它的代码如下所示:
**SurfaceComposerClient.cpp**
~~~
spSurfaceComposerClient::createSurface(
int pid,const String8& name,DisplayID display,uint32_t w,
uint32_t h,PixelFormat format,uint32_t flags)
{
sp result;
if(mStatus == NO_ERROR) {
ISurfaceFlingerClient::surface_data_t data;
//调用BpSurfaceFlingerClient的createSurface函数
sp surface = mClient->createSurface(&data, pid,name,
display, w, h,format, flags);
if(surface != 0) {
if (uint32_t(data.token) < NUM_LAYERS_MAX) {
//以返回的ISurface对象创建一个SurfaceControl对象
result = new SurfaceControl(this, surface, data, w, h,
format, flags);
}
}
}
returnresult;//返回的是SurfaceControl对象
}
~~~
请求端的处理比较简单:
- 调用跨进程的createSurface函数,得到一个ISurface对象,根据Binder一章的知识可知,这个对象的真实类型是BpSurface。不过以后统称之为ISurface。
- 以这个ISurface对象为参数,构造一个SurfaceControl对象。
createSurface函数的响应端在SurfaceFlinger进程中,下面去看这个函数。
在Surface系统定义了很多类型,咱们也中途休息一下,不妨来看看和字符串“Surface”有关的有多少个类,权当其为小小的
娱乐:
Native层有Surface、ISurface、SurfaceControl、SurfaceComposerClient。
Java层有Surface、SurfaceSession。
上面列出的还只是一部分,后面还有呢!*&@&*%¥*
(2)分析createSurface的响应端
前面讲过,可把BClient看作是SF的Proxy,它会把来自客户端的请求派发给SF处理,通过代码来看看,是不是这样的?如下所示:
**SurfaceFlinger.cpp**
~~~
sp BClient::createSurface(
ISurfaceFlingerClient::surface_data_t* params, int pid,
const String8& name,
DisplayID display, uint32_t w, uint32_t h, PixelFormat format,
uint32_t flags)
{
//果然是交给SF处理,以后我们将跳过BClient这个代理。
return mFlinger->createSurface(mId, pid,name, params, display, w, h,
format, flags);
}
~~~
来看createSurface函数,它的目的就是创建一个ISurface对象,不过这中间的玄机还挺多,代码如下所示:
**SurfaceFlinger.cpp**
~~~
spSurfaceFlinger::createSurface(ClientID clientId, int pid,
const String8& name, ISurfaceFlingerClient::surface_data_t* params,
DisplayID d, uint32_t w, uint32_t h, PixelFormat format,
uint32_t flags)
{
sp layer;//LayerBaseClient是Layer家族的基类
//这里又冒出一个LayerBaseClient的内部类,它也叫Surface,是不是有点头晕了?
sp surfaceHandle;
Mutex::Autolock _l(mStateLock);
//根据clientId找到createConnection时加入的那个Client对象
sp client = mClientsMap.valueFor(clientId);
......
//注意这个id,它的值表示Client创建的是第几个显示层,根据图8-14可以看出,这个id
//同时也表示将使用SharedBufferStatck数组的第id个元素。
int32_t id = client->generateId(pid);
//一个Client不能创建多于NUM_LAYERS_MAX个的Layer。
if(uint32_t(id) >= NUM_LAYERS_MAX) {
return surfaceHandle;
}
//根据flags参数来创建不同类型的显示层,我们在8.4.1节介绍过相关知识
switch(flags & eFXSurfaceMask) {
case eFXSurfaceNormal:
if (UNLIKELY(flags & ePushBuffers)) {
//创建PushBuffer类型的显示层,我们将在拓展思考部分分析它
layer = createPushBuffersSurfaceLocked(client, d, id,
w, h, flags);
} else {
//①创建Normal类型的显示层,我们分析待会这个
layer = createNormalSurfaceLocked(client, d, id,
w, h, flags, format);
}
break;
case eFXSurfaceBlur:
//创建Blur类型的显示层
layer = createBlurSurfaceLocked(client, d, id, w, h, flags);
break;
case eFXSurfaceDim:
//创建Dim类型的显示层
layer = createDimSurfaceLocked(client, d, id, w, h, flags);
break;
}
if(layer != 0) {
layer->setName(name);
setTransactionFlags(eTransactionNeeded);
//从显示层对象中取出一个ISurface对象赋值给SurfaceHandle
surfaceHandle = layer->getSurface();
if(surfaceHandle != 0) {
params->token = surfaceHandle->getToken();
params->identity = surfaceHandle->getIdentity();
params->width = w;
params->height = h;
params->format = format;
}
}
returnsurfaceHandle;//ISurface的Bn端就是这个对象。
}
~~~
上面代码中的函数倒是很简单,知识代码里面冒出来的几个新类型和它们的名字却让人有点头晕。先用文字总结一下:
- LayerBaseClient:前面提到的显示层在代码中的对应物,就是这个LayerBaseClient,不过这是一个大家族,不同类型的显示层将创建不同类型的LayerBaseClient。
- LayerBaseClient中有一个内部类,名字叫Surface,这是一个支持Binder通信的类,它派生于ISurface。
关于Layer的故事,后面会有单独的章节来介绍。这里先继续分析createNormalSurfaceLocked函数。它的代码如下所示:
**SurfaceFlinger.cpp**
~~~
spSurfaceFlinger::createNormalSurfaceLocked(
const sp& client, DisplayID display,
int32_t id, uint32_t w, uint32_t h, uint32_t flags,
PixelFormat& format)
{
switch(format) { //一些图像方面的参数设置,可以不去管它。
casePIXEL_FORMAT_TRANSPARENT:
casePIXEL_FORMAT_TRANSLUCENT:
format = PIXEL_FORMAT_RGBA_8888;
break;
casePIXEL_FORMAT_OPAQUE:
format = PIXEL_FORMAT_RGB_565;
break;
}
//①创建一个Layer类型的对象
sp layer = new Layer(this, display,client, id);
//②设置Buffer
status_t err = layer->setBuffers(w, h, format, flags);
if (LIKELY(err == NO_ERROR)) {
//初始化这个新layer的一些状态
layer->initStates(w, h, flags);
//③ 还记得在图8-10中提到的Z轴吗?下面这个函数把这个layer加入到Z轴大军中。
addLayer_l(layer);
}
......
returnlayer;
}
~~~
createNormalSurfaceLocked函数有三个关键点,它们是:
- 构造一个Layer对象。
- 调用Layer对象的setBuffers函数。
- 调用SF的addLayer_l函数。
暂且记住这三个关键点,后文有单独章节分析它们。先继续分析SurfaceControl的流程。
(3)创建SurfaceControl对象
当跨进程的createSurface调用返回一个ISurface对象时,将通过下面的代码创建一个SurfaceControl对象:
~~~
result = new SurfaceControl(this, surface, data,w, h,format, flags);
~~~
下面来看这个SurfaceControl对象为何物。它的代码如下所示:
**SurfaceControl.cpp**
~~~
SurfaceControl::SurfaceControl(
const sp& client,
const sp& surface,
const ISurfaceFlingerClient::surface_data_t& data,
uint32_t w, uint32_t h, PixelFormat format, uint32_t flags)
//mClient为SurfaceComposerClient,而mSurface指向跨进程createSurface调用
//返回的ISurface对象。
:mClient(client), mSurface(surface),
mToken(data.token), mIdentity(data.identity),
mWidth(data.width), mHeight(data.height), mFormat(data.format),
mFlags(flags)
{
}
~~~
SurfaceControl类可以看作是一个wrapper类:
它封装了一些函数,通过这些函数可以方便地调用mClient或ISurface提供的函数。
在SurfaceControl的分析过程中,还遗留了和Layer相关的部分,下面就来解决它们。
2. Layer和它的家族
我们在createSurface中创建的是Normal的Layer,下面先看这个Layer的构造函数。
(1)Layer的构造
Layer是从LayerBaseClient派生的,其代码如下所示:
**Layer.cpp**
~~~
Layer::Layer(SurfaceFlinger* flinger, DisplayIDdisplay,
const sp& c, int32_t i)//这个i表示SharedBufferStack数组的索引
: LayerBaseClient(flinger, display, c, i),//先调用基类构造函数
mSecure(false),
mNoEGLImageForSwBuffers(false),
mNeedsBlending(true),
mNeedsDithering(false)
{
//getFrontBuffer实际取出的是FrontBuffer的位置
mFrontBufferIndex = lcblk->getFrontBuffer();
}
~~~
再来看基类LayerBaseClient的构造函数,代码如下所示:
**LayerBaseClient.cpp**
~~~
LayerBaseClient::LayerBaseClient(SurfaceFlinger*flinger, DisplayID display,
const sp& client, int32_t i)
:LayerBase(flinger, display), lcblk(NULL), client(client), mIndex(i),
mIdentity(uint32_t(android_atomic_inc(&sIdentity)))
{
/*
创建一个SharedBufferServer对象,注意它使用了SharedClient对象,
并且传入了表示SharedBufferStack数组索引的i和一个常量NUM_BUFFERS
*/
lcblk = new SharedBufferServer(
client->ctrlblk, i, NUM_BUFFERS,//该值为常量2,在Layer.h中定义
mIdentity);
}
~~~
SharedBufferServer是什么?它和SharedClient有什么关系?
其实,之前在介绍SharedClient时曾提过与此相关的内容,这里再来认识一下,先看图8-15:
:-: ![](http://img.blog.csdn.net/20150802162659551?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
图8-15 ShardBufferServer的示意图
根据上图并结合前面的介绍,可以得出以下结论:
- 在SF进程中,Client的一个Layer将使用SharedBufferStack数组中的一个成员,并通过SharedBufferServer结构来控制这个成员,我们知道SF是消费者,所以可由SharedBufferServer来控制数据的读取。
- 与之相对应,客户端的进程也会有一个对象来使用这个SharedBufferStatck,可它是通过另外一个叫SharedBufferClient的结构来控制的。客户端为SF提供数据,所以可由SharedBufferClient控制数据的写入。在后文的分析中还会碰到SharedBufferClient。
注意,在拓展思考部分,会有单独章节来分析生产/消费过程中的读写控制。
通过前面的代码可知,Layer对象被new出来后,传给了一个sp对象,读者还记得sp中的onFirstRef函数吗?Layer家族在这个函数中还有一些处理。一起去看看,但这个函数由基类LayerBaseClient实现。
**LayerBase.cpp**
~~~
void LayerBaseClient::onFirstRef()
{
sp client(this->client.promote());
if (client != 0) {
//把自己加入client对象的mLayers数组中,这部分内容比较简单,读者可以自行研究
client->bindLayer(this, mIndex);
}
}
~~~
好,Layer创建完毕,下面来看第二个重要的函数setBuffers。
(2)setBuffers的分析
setBuffers,Layer类以及Layer的基类都有实现。由于创建的是Layer类型的对象,所以请读者直接到Layer.cpp中寻找setBuffers函数。这个函数的目的就是创建用于PageFlipping的FrontBuffer和BackBuffer。一起来看,代码如下所示:
**Layer.cpp**
~~~
status_t Layer::setBuffers( uint32_t w, uint32_th,
PixelFormat format,uint32_t flags)
{
PixelFormatInfo info;
status_t err = getPixelFormatInfo(format, &info);
if(err) return err;
//DisplayHardware是代表显示设备的HAL对象,0代表第一块屏幕的显示设备。
//这里将从HAL中取出一些和显示相关的信息。
constDisplayHardware& hw(graphicPlane(0).displayHardware());
uint32_t const maxSurfaceDims = min(
hw.getMaxTextureSize(), hw.getMaxViewportDims());
PixelFormatInfo displayInfo;
getPixelFormatInfo(hw.getFormat(),&displayInfo);
constuint32_t hwFlags = hw.getFlags();
......
/*
创建Buffer,这里将创建两个GraphicBuffer。这两个GraphicBuffer就是我们前面
所说的FrontBuffer和BackBuffer。
*/
for (size_t i=0 ; i& layer)
{
/*
mCurrentState是SurfaceFlinger定义的一个结构,它有一个成员变量叫
layersSortedByZ,其实就是一个排序数组。下面这个add函数将把这个新的layer按照
它在Z轴的位置加入到排序数组中。mCurrentState保存了所有的显示层。
*/
ssize_t i = mCurrentState.layersSortedByZ.add(
layer,&LayerBase::compareCurrentStateZ);
sp lbc =
LayerBase::dynamicCast< LayerBaseClient*>(layer.get());
if(lbc != 0) {
mLayerMap.add(lbc->serverIndex(), lbc);
}
returnNO_ERROR;
}
~~~
对Layer的三个关键函数都已分析过了,下面正式介绍Layer家族。
(4)Layer家族的介绍
前面的内容确让人头晕眼花,现在应该帮大家恢复清晰的头脑。先来“一剂猛药”,见图8-16:
:-: ![](http://img.blog.csdn.net/20150802162717491?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
图8-16 Layer家族
通过上图可知:
- LayerBaseClient从LayerBase类派生。
- LayerBaseClient还有四个派生类,分别是Layer、LayerBuffer、LayerDim和LayerBlur。
- LayerBaseClient定义了一个内部类Surface,这个Surface从ISurface类派生,它支持Binder通信。
- 针对不同的类型,Layer和LayerBuffer分别有一个内部类SurfaceLayer和SurfaceLayerBuffer,它们继承了LayerBaseClient的Surface类。所以对于Normal类型的显示层来说,getSurface返回的ISurface对象的真正类型是SurfaceLayer。
- LayerDim和LayerBlur类没有定义自己的内部类,所以对于这两种类型的显示层来说,它们直接使用了LayerBaseClient的Surface。
- ISurface接口提供了非常简单的函数,如requestBuffer、postBuffer等。
这里大量使用了内部类。我们知道,内部类最终都会把请求派发给外部类对象来处理,既然如此,在以后分析中,如果没有特殊情况,就会直接跳到外部类的处理函数中。
强烈建议Google把Surface相关代码好好整理一下,至少让类型名取得更直观些,现在这样确实有点让人头晕。好,来小小娱乐一下。看之前介绍的和“Surface”有关的名字:
Native层有Surface、ISurface、SurfaceControl、SurfaceComposerClient。
Java层有Surface、SurfaceSession。
在介绍完Layer家族后,与它相关的名字又多了几个,它们是
LayerBaseClient::Surface、Layer::SurfaceLayer、LayerBuffer::SurfaceLayerBuffer。
3. SurfaceControl总结
SurfaceControl创建后得到了什么呢?可用图8-17来表示:
:-: ![](http://img.blog.csdn.net/20150802162734012?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
图8-17 SurfaceControl创建后的结果图
通过上图可以知道:
- mClient成员变量指向SurfaceComposerClient。
- mSurface的Binder通信响应端为SurfaceLayer。
- SurfaceLayer有一个变量mOwner指向它的外部类Layer,而Layer有一个成员变量mSurface指向SurfaceLayer。这个SurfaceLayer对象由getSurface函数返回。
>[info] **注意**,mOwner变量由SurfaceLayer的基类Surface(LayBaseClient的内部类)定义。
接下来就是writeToParcel分析和Native Surface对象的创建了。注意,这个Native的Surface可不是LayBaseClient的内部类Surface。
';