android surfaceflinger研究----Surface机制
前一篇文章介绍了android的显示系统,这篇文章中,我们把视角往上层移动一下,研究一下framework是如何与surfaceflinger进行业务交互的。如何创建surface,如何显示窗口等等,所有的这一切都是通过系统服务WindowManagerService与surfaceflinger来进行的。
android中的Surface机制这一块代码写的比较难理解,光叫Surface的类就有3个,因此本篇文章从两部分来分析,首先,想要理解Surface机制,还是需要首先理清各个类之间的关系。其次,在理解了整个Surface机制的类关系之后,到时我们再结合前一篇文章中对显示系统的介绍,研究一下一个Surface是如何和显示系统建立起联系来的,这个联系主要是指Surface的显示buffer的存储管理。在下篇文章中,再分析SurfaceFlinger是如何将已经存储了窗口图形数据的Surface
Buffer显示到显示系统中。。
1. Surface机制的静态关系
将这一部分叫做Surface机制,是有别于SurfaceFlinger而言的,android的图形系统中,作为C/S模型两端的WMS和SurfaceFlinger是图形系统业务的核心,但是不把WMS和SurfaceFlinger中间的这层联系搞清楚的话,是很难理解整个图形系统的,在本文中我将两者之间的这个联系关系称之为Surface机制,它的主要任务就是创建一个Surface,ViewRoot在这个Surface上描绘当前的窗口,SurfaceFlinger将这个Surface flinger(扔)给显示系统将其呈现在硬件设备上。其实这里这个Surface在不同的模块中是以不同的形态存在的,唯一不变的就是其对应的显示Buffer。
1.1 ViewRoot和WMS共享Surface
我们知道每个Activity都会有一个ViewRoot作为Activity Window与WMS交互的接口,ViewRoot会绘制整个Activity的窗口View到Surface上,因此我们在ViewRoot中就有了创建Surface的需求。看一下代码中的Surface的定义:relayoutWindow()@ViewRoot.java
- <spanstyle="font-size:13px;">privatefinalSurfacemSurface=newSurface();</span>
- <spanstyle="font-size:13px;">publicSurface(){
- if(DEBUG_RELEASE){
- mCreationStack=newException();
- }
- mCanvas=newCompatibleCanvas();
- }</span>
relayoutWindow()@ViewRoot.java
- <spanstyle="font-size:13px;">intrelayoutResult=sWindowSession.relayout(
- mWindow,params,
- (int)(mView.mMeasuredWidth*appScale+0.5f),
- (int)(mView.mMeasuredHeight*appScale+0.5f),
- viewVisibility,insetsPending,mWinFrame,
- mPendingContentInsets,mPendingVisibleInsets,
- mPendingConfiguration,mSurface);</span>
- <spanstyle="font-size:13px;">Surfacesurface=win.createSurfaceLocked();
- if(surface!=null){
- outSurface.copyFrom(surface);
- win.mReportDestroySurface=false;
- win.mSurfacePendingDestroy=false;
- if(SHOW_TRANSACTIONS)Slog.i(TAG,
- "OUTSURFACE"+outSurface+":copied");
- }else{</span>
1.2SurfaceSession
SurfaceSession可以认为是创建Surface过程中,WMS和SurfaceFlinger之间的会话层,通过这个SurfaceSession实现了Surface的创建。
SurfaceSession是JAVA层的概念,@SurfaceSession.java。它对应的native实体是一个SurfaceComposerClient对象。
SurfaceComposerClient通过ComposerService类来获得SurfaceFlinger的IBinder接口,但是光获得SurfaceFlinger的IBinder接口是不够的,要想请求SurfaceFlinger创建一个Surface,还需要向SurfaceFlinger获得一个IBinder接口ISurfaceComposerClient,通过这个ISurfaceComposerClient来请求SurfaceFlinger创建一个Surface,为什么这么绕呢,为什么不直接让SurfaceFlinger创建Surface呢?
站在SurfaceFlinger的角度来考虑,对于SurfaceFlinger来说,可能有多个Client来请求SurfaceFlinger的业务,每个Client可能会请求SurfaceFlinger创建多个Surface,那么SurfaceFlinger本地需要提供一套机制来保存每个client请求创建的Surface,SurfaceFlinger通过为每个client创建一个Client对象实现这个机制,并将这个Client的IBinder接口ISurfaceComposerClient返给SurfaceComposerClient对象。SurfaceComposerClient对象在通过ISurfaceComposerClient去请求创建Surface。
@SurfaceFlinger.h
- classClient:publicBnSurfaceComposerClient
@SurfaceComposerClient.cpp
- voidSurfaceComposerClient::onFirstRef()
- {
- sp<ISurfaceComposer>sm(getComposerService());
- if(sm!=0){
- sp<ISurfaceComposerClient>conn=sm->createConnection();
- if(conn!=0){
- mClient=conn;
- Composer::addClient(this);
- mPrebuiltLayerState=newlayer_state_t;
- mStatus=NO_ERROR;
- }
- }
- }
下图描述了整个SurfaceSession的内部结构与工作流程。
其中蓝色箭头是SurfaceComposerClient通过ComposerService获得SurfaceFlinger的IBinder接口ISurfaceComposer过程;
红色箭头表示SurfaceComposerClient通过IPC请求SurfaceFlinger创建Client的过程,并获得Client的IBinder接口ISurfaceComposerClient;
绿色箭头表示SurfaceComposerClient通过IPC请求Client创建Surface。
1.3 Surface的形态
上一节我们分析了SurfaceSession的静态结构,得知Surface的创建过程是通过SurfaceSession这个中间会话层去请求SurfaceFlinger去创建的,并且这篇文章中,我们说了半天Surface了,那么究竟我们要创建的Surface究竟是什么样的一个东西呢,它的具体形态是什么呢?这一小节我们就来分析以下Surface的形态。
1.3.1 client端Surface的形态
首先,我们看一下Surface在WMS中定义的代码
createSurfaceLocked()@WindowManagerService.java
- mSurface=newSurface(
- mSession.mSurfaceSession,mSession.mPid,
- mAttrs.getTitle().toString(),
- 0,w,h,mAttrs.format,flags);
@Surface.java
- publicSurface(SurfaceSessions,
- intpid,intdisplay,intw,inth,intformat,intflags)
- throwsOutOfResourcesException{
- if(DEBUG_RELEASE){
- mCreationStack=newException();
- }
- mCanvas=newCompatibleCanvas();
- init(s,pid,null,display,w,h,format,flags);
- }
Native 函数init回调到SurfaceComposerClient的createSurface()函数,往下的过程在上一节的图中描述的很清楚,流程就不介绍了,同时我们先不管SurfaceFlinger为SurfaceComposerClient创建的Surface到底是一个什么东西,我们先看看SurfaceComposerClient为WMS创建的是一个什么东西?
@SurfaceComposerClient.cpp
- sp<SurfaceControl>SurfaceComposerClient::createSurface(
- intpid,
- constString8&name,
- DisplayIDdisplay,
- uint32_tw,
- uint32_th,
- PixelFormatformat,
- uint32_tflags)
- {
- sp<SurfaceControl>result;
- if(mStatus==NO_ERROR){
- ISurfaceComposerClient::surface_data_tdata;
- sp<ISurface>surface=mClient->createSurface(&data,pid,name,
- display,w,h,format,flags);
- if(surface!=0){
- result=newSurfaceControl(this,surface,data,w,h,format,flags);
- }
- }
- returnresult;
- }
从上面的代码我们可以看出,SurfaceComposerClient为WMS返回的是一个SurfaceControl对象,这个SurfaceControl对象包含了surfaceFlinger为SurfaceComposerClient创建的surface,这个surfaceFlinge创建的Surface在Client端的形态为ISurface。这个过程下面分析SurfaceFlinger端的Surface形态时会看到。
SurfaceControl类中还有一个非常重要的成员,它的类型也叫做Surface,定义在frameworks/base/libs/surfaceflinger/Surface.h。这个Surface提供了显示Buffer的管理。在文章的后面再介绍。
@frameworks/base/libs/surfaceflinger_client/Surface.cpp
- sp<Surface>SurfaceControl::getSurface()const
- {
- Mutex::Autolock_l(mLock);
- if(mSurfaceData==0){
- mSurfaceData=newSurface(const_cast<SurfaceControl*>(this));
- }
- returnmSurfaceData;
- }
1.3.2 SurfaceFlinger端Surface形态
- sp<Layer>normalLayer;
- switch(flags&eFXSurfaceMask){
- caseeFXSurfaceNormal:
- if(UNLIKELY(flags&ePushBuffers)){
- layer=createPushBuffersSurface(client,d,w,h,flags);
- }else{
- normalLayer=createNormalSurface(client,d,w,h,flags,format);
- layer=normalLayer;
- }
- break;
- caseeFXSurfaceBlur:
- layer=createBlurSurface(client,d,w,h,flags);
- break;
- caseeFXSurfaceDim:
- layer=createDimSurface(client,d,w,h,flags);
- break;
- }
- if(layer!=0){
- layer->initStates(w,h,flags);
- layer->setName(name);
- ssize_ttoken=addClientLayer(client,layer);
- surfaceHandle=layer->getSurface();
- if(surfaceHandle!=0){
- params->token=token;
- params->identity=surfaceHandle->getIdentity();
- params->width=w;
- params->height=h;
- params->format=format;
- if(normalLayer!=0){
- Mutex::Autolock_l(mStateLock);
- mLayerMap.add(surfaceHandle->asBinder(),normalLayer);
- }
- }
当client请求SurfaceFlinger创建Surface时,SurfaceFlinger首先根据WMS提供的窗口的属性来一个命名为Layer概念的对象,然后再根据Layer创建它的子类对象LayerBaseClient::Surface。此时第三个名为Surface类出现了,下一节我们来介绍一下这个Layer的概念。
1.4 Layer
1.4.1 Layer的分类
目前,android中有4中Layer类型,如上图所示。
1.Layer, 普通的Layer,它为每个Client端请求的Surface创建显示Buffer。
2.LayerBuffer,这种Layer它并不会创建显示Buffer,它只是使用已有的Buffer作为显示Buffer,如Camera的preview;
3.LayerBlur,这种Layer也不会创建显示Buffer,它只是将通过这个Layer将原来FrameBuffer上的数据进行模糊处理;
4.LayerDim,这种Layer也不会创建显示Buffer,它只是将通过这个Layer将原来FrameBuffer上的数据进行暗淡处理;
从这中Layer看出,我们分析的重点就是第一种Layer,下面我们着重分析一下普通的Layer。Layer的具体业务我们在下一篇文章中分析
1.4.2 Layer的管理
上文我们在分析SurfaceSession的时候,也分析过,一个Client可能会创建多个Surface,也就是要创建多个Layer,那么SurfaceFlinger端如何管理这个写个Layer呢?SurfaceFlinger维护了2个Vector来管理Layer。
第一种方式,我们知道SurfaceFlinger会为每个SurfaceSession创建一个Client对象,这第一种方式就是将所有为某一个SurfacSession创建的Layer保存在它对应的Client对象中。
SurfaceFlinger::createSurface()@SurfaceFlinger.cpp
- ssize_ttoken=addClientLayer(client,layer);
第二种方式,将所有的创建的普通的Layer保存起来,以便Client Surface在请求实现Buffer时能够辨识Client Surface对应的Layer。
SurfaceFlinger::createSurface()@SurfaceFlinger.cpp
- mLayerMap.add(surfaceHandle->asBinder(),normalLayer);
2. Surface 显示Buffer的存储管理
在前文介绍Client端的Surface形态的内容时,我们提到SurfaceControl中还会维护一个名为Surface对象,它定义在frameworks/base/libs/surfaceflinger/Surface.h中,它负责向LayerBaseClient::Surface请求显示Buffer,同时将显示Buffer交给JAVA Surface的Canvas去绘制窗口,我们称这个Surface为Client Surface。
2.1 窗口绘制
draw()@ViewRoot.java
- Canvascanvas;
- try{
- intleft=dirty.left;
- inttop=dirty.top;
- intright=dirty.right;
- intbottom=dirty.bottom;
- canvas=surface.lockCanvas(dirty);
- if(left!=dirty.left||top!=dirty.top||right!=dirty.right||
- bottom!=dirty.bottom){
- mAttachInfo.mIgnoreDirtyState=true;
- }
- //TODO:Dothisinnative
- canvas.setDensity(mDensity);
- staticjobjectSurface_lockCanvas(JNIEnv*env,jobjectclazz,jobjectdirtyRect)
- {
- constsp<Surface>&surface(getSurface(env,clazz));
- if(!Surface::isValid(surface))
- return0;
- SkCanvas*nativeCanvas=(SkCanvas*)env->GetIntField(canvas,no.native_canvas);
- SkBitmapbitmap;
- ssize_tbpr=info.s*bytesPerPixel(info.format);
- bitmap.setConfig(convertPixelFormat(info.format),info.w,info.h,bpr);
- if(info.format==PIXEL_FORMAT_RGBX_8888){
- bitmap.setIsOpaque(true);
- }
- if(info.w>0&&info.h>0){
- bitmap.setPixels(info.bits);
- }else{
- //besafewithanemptybitmap.
- bitmap.setPixels(NULL);
- }
- nativeCanvas->setBitmapDevice(bitmap);
- SkRegionclipReg;
- if(dirtyRegion.isRect()){//verycommoncase
- constRectb(dirtyRegion.getBounds());
- clipReg.setRect(b.left,b.top,b.right,b.bottom);
- }else{
- size_tcount;
- Rectconst*r=dirtyRegion.getArray(&count);
- while(count){
- clipReg.op(r->left,r->top,r->right,r->bottom,SkRegion::kUnion_Op);
- r++,count--;
- }
- }
- nativeCanvas->clipRegion(clipReg);
- intsaveCount=nativeCanvas->save();
- env->SetIntField(clazz,so.saveCount,saveCount);
- if(dirtyRect){
- constRect&bounds(dirtyRegion.getBounds());
- env->SetIntField(dirtyRect,ro.l,bounds.left);
- env->SetIntField(dirtyRect,ro.t,bounds.top);
- env->SetIntField(dirtyRect,ro.r,bounds.right);
- env->SetIntField(dirtyRect,ro.b,bounds.bottom);
- }
- returncanvas;
- }
上面的代码,我们可以看出,Canvas的Bitmap设备的设置了Client Surface的显示Buffer为其Bitmap pixel存储空间。
- bitmap.setPixels(info.bits);
这样Canvas的绘制空间就有了。下一步就该绘制窗口了。
draw()@ViewRoot.java
- try{
- canvas.translate(0,-yoff);
- if(mTranslator!=null){
- mTranslator.translateCanvas(canvas);
- }
- canvas.setScreenDensity(scalingRequired
- ?DisplayMetrics.DENSITY_DEVICE:0);
- mView.draw(canvas);
- }
2.2Client Surface的初始化
Client Surface的创建是从ViewRoot首次Lock canvas时进行的,这么做的目的可能也是为了节约空间,减少不必要的开支。
Client Surface的初始化和显示Buffer的管理过程比较复杂,下图给出了这一部分的一个静态结构图,有些东西从图上表现不出来,下面我简单的介绍一下。
2.2.1SharedClient
SharedClient是这一部分实现的关键所在,它并不是一个每个Client Surface创建时都会被创建的,整个系统中只有一个SharedClient对象,并且它是在共享内存上创建的,下面代码中可以看出,UserClient在初始化时,提供了一个MemoryHeapBase来供SharedClient创建,MemoryHeapBase是创建的共享内存。@SurfaceFlinger.cpp
- UserClient::UserClient(constsp<SurfaceFlinger>&flinger)
- :ctrlblk(0),mBitmap(0),mFlinger(flinger)
- {
- constintpgsize=getpagesize();
- constintcblksize=((sizeof(SharedClient)+(pgsize-1))&~(pgsize-1));
- mCblkHeap=newMemoryHeapBase(cblksize,0,
- "SurfaceFlingerClientcontrol-block");
- ctrlblk=static_cast<SharedClient*>(mCblkHeap->getBase());
- if(ctrlblk){//constructthesharedstructurein-place.
- new(ctrlblk)SharedClient;
- }
- }
SharedClient对象的主要目的其实很简单,就是为系统提供了SharedBufferStack::NUM_LAYERS_MAX(GB上为31)个SharedBufferStack。也就是目前系统同时支持31个Client Surface的创建。关于SharedBufferStack下面再做介绍。
为什么需要将SharedClient设计为共享内存呢?每个Client Surface需要的SharedBufferStack寄存在SharedClient中,而对于每个SharedBufferStack,一方面,Client Surface需要对它进行一些区域尺寸等的设置;另一方面,在render时,Layer需要获得当前Client Surfce对应的SharedBufferStack中获得区域尺寸等设置信息。
class [email protected]
- SharedBufferStacksurfaces[SharedBufferStack::NUM_LAYERS_MAX];
2.2.2SharedBufferStack
- status_tsetDirtyRegion(intbuffer,constRegion®);
- status_tsetCrop(intbuffer,constRect®);
- status_tsetTransform(intbuffer,uint8_ttransform);
- volatileint32_thead;//server'scurrentfrontbuffer
- volatileint32_tavailable;//numberofdequeue-ablebuffers
2.2.3 Client Surace GraphicBuffer的请求
这里将Client Surface的GraphicBuffer的创建过程以时序图的形式展现出来。
这里需要注意的是,Client Surface的2个GraphicBuffer只有在lock()时才会去创建,而不是在Client Surface被创建的时候创建的。
前一篇文章介绍了android的显示系统,这篇文章中,我们把视角往上层移动一下,研究一下framework是如何与surfaceflinger进行业务交互的。如何创建surface,如何显示窗口等等,所有的这一切都是通过系统服务WindowManagerService与surfaceflinger来进行的。
android中的Surface机制这一块代码写的比较难理解,光叫Surface的类就有3个,因此本篇文章从两部分来分析,首先,想要理解Surface机制,还是需要首先理清各个类之间的关系。其次,在理解了整个Surface机制的类关系之后,到时我们再结合前一篇文章中对显示系统的介绍,研究一下一个Surface是如何和显示系统建立起联系来的,这个联系主要是指Surface的显示buffer的存储管理。在下篇文章中,再分析SurfaceFlinger是如何将已经存储了窗口图形数据的Surface
Buffer显示到显示系统中。。
1. Surface机制的静态关系
将这一部分叫做Surface机制,是有别于SurfaceFlinger而言的,android的图形系统中,作为C/S模型两端的WMS和SurfaceFlinger是图形系统业务的核心,但是不把WMS和SurfaceFlinger中间的这层联系搞清楚的话,是很难理解整个图形系统的,在本文中我将两者之间的这个联系关系称之为Surface机制,它的主要任务就是创建一个Surface,ViewRoot在这个Surface上描绘当前的窗口,SurfaceFlinger将这个Surface flinger(扔)给显示系统将其呈现在硬件设备上。其实这里这个Surface在不同的模块中是以不同的形态存在的,唯一不变的就是其对应的显示Buffer。
1.1 ViewRoot和WMS共享Surface
我们知道每个Activity都会有一个ViewRoot作为Activity Window与WMS交互的接口,ViewRoot会绘制整个Activity的窗口View到Surface上,因此我们在ViewRoot中就有了创建Surface的需求。看一下代码中的Surface的定义:relayoutWindow()@ViewRoot.java
- <spanstyle="font-size:13px;">privatefinalSurfacemSurface=newSurface();</span>
- <spanstyle="font-size:13px;">publicSurface(){
- if(DEBUG_RELEASE){
- mCreationStack=newException();
- }
- mCanvas=newCompatibleCanvas();
- }</span>
relayoutWindow()@ViewRoot.java
- <spanstyle="font-size:13px;">intrelayoutResult=sWindowSession.relayout(
- mWindow,params,
- (int)(mView.mMeasuredWidth*appScale+0.5f),
- (int)(mView.mMeasuredHeight*appScale+0.5f),
- viewVisibility,insetsPending,mWinFrame,
- mPendingContentInsets,mPendingVisibleInsets,
- mPendingConfiguration,mSurface);</span>
- <spanstyle="font-size:13px;">Surfacesurface=win.createSurfaceLocked();
- if(surface!=null){
- outSurface.copyFrom(surface);
- win.mReportDestroySurface=false;
- win.mSurfacePendingDestroy=false;
- if(SHOW_TRANSACTIONS)Slog.i(TAG,
- "OUTSURFACE"+outSurface+":copied");
- }else{</span>
1.2SurfaceSession
SurfaceSession可以认为是创建Surface过程中,WMS和SurfaceFlinger之间的会话层,通过这个SurfaceSession实现了Surface的创建。
SurfaceSession是JAVA层的概念,@SurfaceSession.java。它对应的native实体是一个SurfaceComposerClient对象。
SurfaceComposerClient通过ComposerService类来获得SurfaceFlinger的IBinder接口,但是光获得SurfaceFlinger的IBinder接口是不够的,要想请求SurfaceFlinger创建一个Surface,还需要向SurfaceFlinger获得一个IBinder接口ISurfaceComposerClient,通过这个ISurfaceComposerClient来请求SurfaceFlinger创建一个Surface,为什么这么绕呢,为什么不直接让SurfaceFlinger创建Surface呢?
站在SurfaceFlinger的角度来考虑,对于SurfaceFlinger来说,可能有多个Client来请求SurfaceFlinger的业务,每个Client可能会请求SurfaceFlinger创建多个Surface,那么SurfaceFlinger本地需要提供一套机制来保存每个client请求创建的Surface,SurfaceFlinger通过为每个client创建一个Client对象实现这个机制,并将这个Client的IBinder接口ISurfaceComposerClient返给SurfaceComposerClient对象。SurfaceComposerClient对象在通过ISurfaceComposerClient去请求创建Surface。
@SurfaceFlinger.h
- classClient:publicBnSurfaceComposerClient
@SurfaceComposerClient.cpp
- voidSurfaceComposerClient::onFirstRef()
- {
- sp<ISurfaceComposer>sm(getComposerService());
- if(sm!=0){
- sp<ISurfaceComposerClient>conn=sm->createConnection();
- if(conn!=0){
- mClient=conn;
- Composer::addClient(this);
- mPrebuiltLayerState=newlayer_state_t;
- mStatus=NO_ERROR;
- }
- }
- }
下图描述了整个SurfaceSession的内部结构与工作流程。
其中蓝色箭头是SurfaceComposerClient通过ComposerService获得SurfaceFlinger的IBinder接口ISurfaceComposer过程;
红色箭头表示SurfaceComposerClient通过IPC请求SurfaceFlinger创建Client的过程,并获得Client的IBinder接口ISurfaceComposerClient;
绿色箭头表示SurfaceComposerClient通过IPC请求Client创建Surface。
1.3 Surface的形态
上一节我们分析了SurfaceSession的静态结构,得知Surface的创建过程是通过SurfaceSession这个中间会话层去请求SurfaceFlinger去创建的,并且这篇文章中,我们说了半天Surface了,那么究竟我们要创建的Surface究竟是什么样的一个东西呢,它的具体形态是什么呢?这一小节我们就来分析以下Surface的形态。
1.3.1 client端Surface的形态
首先,我们看一下Surface在WMS中定义的代码
createSurfaceLocked()@WindowManagerService.java
- mSurface=newSurface(
- mSession.mSurfaceSession,mSession.mPid,
- mAttrs.getTitle().toString(),
- 0,w,h,mAttrs.format,flags);
@Surface.java
- publicSurface(SurfaceSessions,
- intpid,intdisplay,intw,inth,intformat,intflags)
- throwsOutOfResourcesException{
- if(DEBUG_RELEASE){
- mCreationStack=newException();
- }
- mCanvas=newCompatibleCanvas();
- init(s,pid,null,display,w,h,format,flags);
- }
Native 函数init回调到SurfaceComposerClient的createSurface()函数,往下的过程在上一节的图中描述的很清楚,流程就不介绍了,同时我们先不管SurfaceFlinger为SurfaceComposerClient创建的Surface到底是一个什么东西,我们先看看SurfaceComposerClient为WMS创建的是一个什么东西?
@SurfaceComposerClient.cpp
- sp<SurfaceControl>SurfaceComposerClient::createSurface(
- intpid,
- constString8&name,
- DisplayIDdisplay,
- uint32_tw,
- uint32_th,
- PixelFormatformat,
- uint32_tflags)
- {
- sp<SurfaceControl>result;
- if(mStatus==NO_ERROR){
- ISurfaceComposerClient::surface_data_tdata;
- sp<ISurface>surface=mClient->createSurface(&data,pid,name,
- display,w,h,format,flags);
- if(surface!=0){
- result=newSurfaceControl(this,surface,data,w,h,format,flags);
- }
- }
- returnresult;
- }
从上面的代码我们可以看出,SurfaceComposerClient为WMS返回的是一个SurfaceControl对象,这个SurfaceControl对象包含了surfaceFlinger为SurfaceComposerClient创建的surface,这个surfaceFlinge创建的Surface在Client端的形态为ISurface。这个过程下面分析SurfaceFlinger端的Surface形态时会看到。
SurfaceControl类中还有一个非常重要的成员,它的类型也叫做Surface,定义在frameworks/base/libs/surfaceflinger/Surface.h。这个Surface提供了显示Buffer的管理。在文章的后面再介绍。
@frameworks/base/libs/surfaceflinger_client/Surface.cpp
- sp<Surface>SurfaceControl::getSurface()const
- {
- Mutex::Autolock_l(mLock);
- if(mSurfaceData==0){
- mSurfaceData=newSurface(const_cast<SurfaceControl*>(this));
- }
- returnmSurfaceData;
- }
1.3.2 SurfaceFlinger端Surface形态
- sp<Layer>normalLayer;
- switch(flags&eFXSurfaceMask){
- caseeFXSurfaceNormal:
- if(UNLIKELY(flags&ePushBuffers)){
- layer=createPushBuffersSurface(client,d,w,h,flags);
- }else{
- normalLayer=createNormalSurface(client,d,w,h,flags,format);
- layer=normalLayer;
- }
- break;
- caseeFXSurfaceBlur:
- layer=createBlurSurface(client,d,w,h,flags);
- break;
- caseeFXSurfaceDim:
- layer=createDimSurface(client,d,w,h,flags);
- break;
- }
- if(layer!=0){
- layer->initStates(w,h,flags);
- layer->setName(name);
- ssize_ttoken=addClientLayer(client,layer);
- surfaceHandle=layer->getSurface();
- if(surfaceHandle!=0){
- params->token=token;
- params->identity=surfaceHandle->getIdentity();
- params->width=w;
- params->height=h;
- params->format=format;
- if(normalLayer!=0){
- Mutex::Autolock_l(mStateLock);
- mLayerMap.add(surfaceHandle->asBinder(),normalLayer);
- }
- }
当client请求SurfaceFlinger创建Surface时,SurfaceFlinger首先根据WMS提供的窗口的属性来一个命名为Layer概念的对象,然后再根据Layer创建它的子类对象LayerBaseClient::Surface。此时第三个名为Surface类出现了,下一节我们来介绍一下这个Layer的概念。
1.4 Layer
1.4.1 Layer的分类
目前,android中有4中Layer类型,如上图所示。
1.Layer, 普通的Layer,它为每个Client端请求的Surface创建显示Buffer。
2.LayerBuffer,这种Layer它并不会创建显示Buffer,它只是使用已有的Buffer作为显示Buffer,如Camera的preview;
3.LayerBlur,这种Layer也不会创建显示Buffer,它只是将通过这个Layer将原来FrameBuffer上的数据进行模糊处理;
4.LayerDim,这种Layer也不会创建显示Buffer,它只是将通过这个Layer将原来FrameBuffer上的数据进行暗淡处理;
从这中Layer看出,我们分析的重点就是第一种Layer,下面我们着重分析一下普通的Layer。Layer的具体业务我们在下一篇文章中分析
1.4.2 Layer的管理
上文我们在分析SurfaceSession的时候,也分析过,一个Client可能会创建多个Surface,也就是要创建多个Layer,那么SurfaceFlinger端如何管理这个写个Layer呢?SurfaceFlinger维护了2个Vector来管理Layer。
第一种方式,我们知道SurfaceFlinger会为每个SurfaceSession创建一个Client对象,这第一种方式就是将所有为某一个SurfacSession创建的Layer保存在它对应的Client对象中。
SurfaceFlinger::createSurface()@SurfaceFlinger.cpp
- ssize_ttoken=addClientLayer(client,layer);
第二种方式,将所有的创建的普通的Layer保存起来,以便Client Surface在请求实现Buffer时能够辨识Client Surface对应的Layer。
SurfaceFlinger::createSurface()@SurfaceFlinger.cpp
- mLayerMap.add(surfaceHandle->asBinder(),normalLayer);
2. Surface 显示Buffer的存储管理
在前文介绍Client端的Surface形态的内容时,我们提到SurfaceControl中还会维护一个名为Surface对象,它定义在frameworks/base/libs/surfaceflinger/Surface.h中,它负责向LayerBaseClient::Surface请求显示Buffer,同时将显示Buffer交给JAVA Surface的Canvas去绘制窗口,我们称这个Surface为Client Surface。
2.1 窗口绘制
draw()@ViewRoot.java
- Canvascanvas;
- try{
- intleft=dirty.left;
- inttop=dirty.top;
- intright=dirty.right;
- intbottom=dirty.bottom;
- canvas=surface.lockCanvas(dirty);
- if(left!=dirty.left||top!=dirty.top||right!=dirty.right||
- bottom!=dirty.bottom){
- mAttachInfo.mIgnoreDirtyState=true;
- }
- //TODO:Dothisinnative
- canvas.setDensity(mDensity);
- staticjobjectSurface_lockCanvas(JNIEnv*env,jobjectclazz,jobjectdirtyRect)
- {
- constsp<Surface>&surface(getSurface(env,clazz));
- if(!Surface::isValid(surface))
- return0;
- SkCanvas*nativeCanvas=(SkCanvas*)env->GetIntField(canvas,no.native_canvas);
- SkBitmapbitmap;
- ssize_tbpr=info.s*bytesPerPixel(info.format);
- bitmap.setConfig(convertPixelFormat(info.format),info.w,info.h,bpr);
- if(info.format==PIXEL_FORMAT_RGBX_8888){
- bitmap.setIsOpaque(true);
- }
- if(info.w>0&&info.h>0){
- bitmap.setPixels(info.bits);
- }else{
- //besafewithanemptybitmap.
- bitmap.setPixels(NULL);
- }
- nativeCanvas->setBitmapDevice(bitmap);
- SkRegionclipReg;
- if(dirtyRegion.isRect()){//verycommoncase
- constRectb(dirtyRegion.getBounds());
- clipReg.setRect(b.left,b.top,b.right,b.bottom);
- }else{
- size_tcount;
- Rectconst*r=dirtyRegion.getArray(&count);
- while(count){
- clipReg.op(r->left,r->top,r->right,r->bottom,SkRegion::kUnion_Op);
- r++,count--;
- }
- }
- nativeCanvas->clipRegion(clipReg);
- intsaveCount=nativeCanvas->save();
- env->SetIntField(clazz,so.saveCount,saveCount);
- if(dirtyRect){
- constRect&bounds(dirtyRegion.getBounds());
- env->SetIntField(dirtyRect,ro.l,bounds.left);
- env->SetIntField(dirtyRect,ro.t,bounds.top);
- env->SetIntField(dirtyRect,ro.r,bounds.right);
- env->SetIntField(dirtyRect,ro.b,bounds.bottom);
- }
- returncanvas;
- }
上面的代码,我们可以看出,Canvas的Bitmap设备的设置了Client Surface的显示Buffer为其Bitmap pixel存储空间。
- bitmap.setPixels(info.bits);
这样Canvas的绘制空间就有了。下一步就该绘制窗口了。
draw()@ViewRoot.java
- try{
- canvas.translate(0,-yoff);
- if(mTranslator!=null){
- mTranslator.translateCanvas(canvas);
- }
- canvas.setScreenDensity(scalingRequired
- ?DisplayMetrics.DENSITY_DEVICE:0);
- mView.draw(canvas);
- }
2.2Client Surface的初始化
Client Surface的创建是从ViewRoot首次Lock canvas时进行的,这么做的目的可能也是为了节约空间,减少不必要的开支。
Client Surface的初始化和显示Buffer的管理过程比较复杂,下图给出了这一部分的一个静态结构图,有些东西从图上表现不出来,下面我简单的介绍一下。
2.2.1SharedClient
SharedClient是这一部分实现的关键所在,它并不是一个每个Client Surface创建时都会被创建的,整个系统中只有一个SharedClient对象,并且它是在共享内存上创建的,下面代码中可以看出,UserClient在初始化时,提供了一个MemoryHeapBase来供SharedClient创建,MemoryHeapBase是创建的共享内存。@SurfaceFlinger.cpp
- UserClient::UserClient(constsp<SurfaceFlinger>&flinger)
- :ctrlblk(0),mBitmap(0),mFlinger(flinger)
- {
- constintpgsize=getpagesize();
- constintcblksize=((sizeof(SharedClient)+(pgsize-1))&~(pgsize-1));
- mCblkHeap=newMemoryHeapBase(cblksize,0,
- "SurfaceFlingerClientcontrol-block");
- ctrlblk=static_cast<SharedClient*>(mCblkHeap->getBase());
- if(ctrlblk){//constructthesharedstructurein-place.
- new(ctrlblk)SharedClient;
- }
- }
SharedClient对象的主要目的其实很简单,就是为系统提供了SharedBufferStack::NUM_LAYERS_MAX(GB上为31)个SharedBufferStack。也就是目前系统同时支持31个Client Surface的创建。关于SharedBufferStack下面再做介绍。
为什么需要将SharedClient设计为共享内存呢?每个Client Surface需要的SharedBufferStack寄存在SharedClient中,而对于每个SharedBufferStack,一方面,Client Surface需要对它进行一些区域尺寸等的设置;另一方面,在render时,Layer需要获得当前Client Surfce对应的SharedBufferStack中获得区域尺寸等设置信息。
class [email protected]
- SharedBufferStacksurfaces[SharedBufferStack::NUM_LAYERS_MAX];
2.2.2SharedBufferStack
- status_tsetDirtyRegion(intbuffer,constRegion®);
- status_tsetCrop(intbuffer,constRect®);
- status_tsetTransform(intbuffer,uint8_ttransform);
- volatileint32_thead;//server'scurrentfrontbuffer
- volatileint32_tavailable;//numberofdequeue-ablebuffers
2.2.3 Client Surace GraphicBuffer的请求
这里将Client Surface的GraphicBuffer的创建过程以时序图的形式展现出来。
这里需要注意的是,Client Surface的2个GraphicBuffer只有在lock()时才会去创建,而不是在Client Surface被创建的时候创建的。