android surfaceflinger研究----Surface机制

android surfaceflinger研究----Surface机制

转自: http://blog.csdn.net/windskier/article/details/7041610,感谢分享微笑

       前一篇文章介绍了android的显示系统,这篇文章中,我们把视角往上层移动一下,研究一下framework是如何与surfaceflinger进行业务交互的。

       1)如何创建surface

       2)如何显示窗口等等

       所有的这一切都是通过系统服务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都会有一个ViewRootImpl作为Activity Window与WMS交互的接口,ViewRootImpl会绘制整个Activity的窗口View到Surface上,因此我们在ViewRootImpl中就有了创建Surface的需求。看一下代码中的Surface的定义:

ViewRootImpl.java

[cpp]  view plain copy
  1. // These can be accessed by any thread, must be protected with a lock.  
  2. // Surface can never be reassigned or cleared (use Surface.clear()).  
  3. private final Surface mSurface = new Surface();  

Surface(SurfaceTexture surfaceTexture)@Surface.java

[cpp]  view plain copy
  1. /** 
  2.  * Create Surface from a {@link SurfaceTexture}. 
  3.  * 
  4.  * Images drawn to the Surface will be made available to the {@link 
  5.  * SurfaceTexture}, which can attach them an OpenGL ES texture via {@link 
  6.  * SurfaceTexture#updateTexImage}. 
  7.  * 
  8.  * @param surfaceTexture The {@link SurfaceTexture} that is updated by this 
  9.  * Surface. 
  10.  */  
  11. public Surface(SurfaceTexture surfaceTexture) {  
  12.     if (DEBUG_RELEASE) {  
  13.         mCreationStack = new Exception();  
  14.     }  
  15.     mCanvas = new CompatibleCanvas();  
  16.     initFromSurfaceTexture(surfaceTexture);  
  17. }  

       由上面可以看出在ViewRootImpl中定义的Surface只是一个空壳,那么真正的Surface是在哪里被初始化的呢?大管家WMS中!当ViewRootImpl请求WMS relayout时,会将ViewSurface中的Surface交给WMS初始化。在WMS中,对应每个WindowState对象,在relayout窗口时,同样会创建一个Surface,wms中的这个Surface会真正的初始化,然后再将这个WMS Surface复制给ViewRootImpl中的Surface。这么实现的目的就是保证ViewRootImpl和WMS共享同一个Surface。ViewRootImpl对Surface进行绘制,WMS对这个Surface进行初始化及管理。很和谐!

relayoutWindow@ViewRootImpl.java

[cpp]  view plain copy
  1. private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,  
  2.         boolean insetsPending) throws RemoteException {  
  3.     ...   
  4.     int relayoutResult = sWindowSession.relayout(  
  5.             mWindow, mSeq, params,  
  6.             (int) (mView.getMeasuredWidth() * appScale + 0.5f),  
  7.             (int) (mView.getMeasuredHeight() * appScale + 0.5f),  
  8.             viewVisibility, insetsPending, mWinFrame,  
  9.             mPendingContentInsets, mPendingVisibleInsets,  
  10.             mPendingConfiguration, mSurface);  
  11.     //Log.d(TAG, "<<<<<< BACK FROM relayout");  
  12.     if (restore) {  
  13.         params.restore();  
  14.     }  
  15.       
  16.     if (mTranslator != null) {  
  17.         mTranslator.translateRectInScreenToAppWinFrame(mWinFrame);  
  18.         mTranslator.translateRectInScreenToAppWindow(mPendingContentInsets);  
  19.         mTranslator.translateRectInScreenToAppWindow(mPendingVisibleInsets);  
  20.     }  
  21.     return relayoutResult;  
  22. }  

relayoutWindow()@WindowManagerService.java

[cpp]  view plain copy
  1. public int relayoutWindow(Session session, IWindow client, int seq,  
  2.         WindowManager.LayoutParams attrs, int requestedWidth,  
  3.         int requestedHeight, int viewVisibility, boolean insetsPending,  
  4.         Rect outFrame, Rect outContentInsets, Rect outVisibleInsets,  
  5.         Configuration outConfig, Surface outSurface) {  
  6.     boolean displayed = false;  
  7.     boolean inTouchMode;  
  8.     boolean configChanged;  
  9.   
  10.     // if they don't have this permission, mask out the status bar bits  
  11.     synchronized(mWindowMap) {  
  12.         WindowState win = windowForClientLocked(session, client, false);  
  13.   
  14.         if (viewVisibility == View.VISIBLE &&  
  15.                 (win.mAppToken == null || !win.mAppToken.clientHidden)) {  
  16.             displayed = !win.isVisibleLw();  
  17.             ...  
  18.             try {  
  19.                 Surface surface = win.createSurfaceLocked();  
  20.                 if (surface != null) {  
  21.                     outSurface.copyFrom(surface);  
  22.                     win.mReportDestroySurface = false;  
  23.                     win.mSurfacePendingDestroy = false;  
  24.                     if (SHOW_TRANSACTIONS) Slog.i(TAG,  
  25.                             "  OUT SURFACE " + outSurface + ": copied");  
  26.                 } else {  
  27.                     // For some reason there isn't a surface.  Clear the  
  28.                     // caller's object so they see the same state.  
  29.                     outSurface.release();  
  30.                 }  
  31.             } catch (Exception e) {  
  32.                 mInputMonitor.updateInputWindowsLw(true /*force*/);  
  33.                   
  34.                 Slog.w(TAG, "Exception thrown when creating surface for client "  
  35.                          + client + " (" + win.mAttrs.getTitle() + ")",  
  36.                          e);  
  37.                 Binder.restoreCallingIdentity(origId);  
  38.                 return 0;  
  39.             }  
  40.             ...  
  41.        }  
  42. }  

1.2 SurfaceSession

     SurfaceSession可以认为是创建Surface过程中,WMS和SurfaceFlinger之间的会话层,通过这个SurfaceSession实现了Surface的创建。 

     一个SurfaceSession表示一个到SurfaceFlinger的连接,通过它可以创建一个或多个Surface实例。

       SurfaceSession是JAVA层的概念,@SurfaceSession.java。它对应的native实体是一个SurfaceComposerClient对象。

       SurfaceComposerClient通过ComposerService类来获得SurfaceFlinger的IBinder接口ISurfaceComposer,但是光获得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(ISurfaceComposerClient的功能只有创建和销毁Surface)。

@SurfaceFlinger.h

[cpp]  view plain copy
  1. class Client : public BnSurfaceComposerClient  
  2.   
  3. class SurfaceFlinger :  
  4.         public BinderService<SurfaceFlinger>,  
  5.         public BnSurfaceComposer,  
  6.         public IBinder::DeathRecipient,  
  7.         protected Thread  


@SurfaceComposerClient.cpp

[cpp]  view plain copy
  1. void SurfaceComposerClient::onFirstRef() {  
  2.     sp<ISurfaceComposer> sm(getComposerService());  
  3.     if (sm != 0) {  
  4.         sp<ISurfaceComposerClient> conn = sm->createConnection();  
  5.         if (conn != 0) {  
  6.             mClient = conn;  
  7.             mStatus = NO_ERROR;  
  8.         }  
  9.     }  
  10. }  

在SurfaceFlinger中对应的执行代码为:

[cpp]  view plain copy
  1. sp<ISurfaceComposerClient> SurfaceFlinger::createConnection()  
  2. {  
  3.     sp<ISurfaceComposerClient> bclient;  
  4.     sp<Client> client(new Client(this));  
  5.     status_t err = client->initCheck();  
  6.     if (err == NO_ERROR) {  
  7.         bclient = client;  
  8.     }  
  9.     return bclient;  
  10. }  

     下图描述了整个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()@WindowState.java

[cpp]  view plain copy
  1. Surface createSurfaceLocked() {  
  2.       if (mSurface == null) {  
  3.           ...  
  4.           try {  
  5.               final boolean isHwAccelerated = (mAttrs.flags &  
  6.                       WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0;  
  7.               final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : mAttrs.format;  
  8.               if (!PixelFormat.formatHasAlpha(mAttrs.format)) {  
  9.                   flags |= Surface.OPAQUE;  
  10.               }  
  11.               mSurface = new Surface(  
  12.                       mSession.mSurfaceSession, mSession.mPid,  
  13.                       mAttrs.getTitle().toString(),  
  14.                       0, w, h, format, flags);  
  15.               if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG,  
  16.                       "  CREATE SURFACE "  
  17.                       + mSurface + " IN SESSION "  
  18.                       + mSession.mSurfaceSession  
  19.                       + ": pid=" + mSession.mPid + " format="  
  20.                       + mAttrs.format + " flags=0x"  
  21.                       + Integer.toHexString(flags)  
  22.                       + " / " + this);  
  23.           }   
  24.           ...  
  25.       }  
  26.       return mSurface;  
  27.   }  

       我们可以看到,它将SurfaceSession对象当作参数传递给了Surface的构造函数。往下看Surface的构造函数。

@Surface.java

[cpp]  view plain copy
  1. /** create a surface with a name @hide */  
  2. public Surface(SurfaceSession s,  
  3.         int pid, String name, int display, int w, int h, int format, int flags)  
  4.     throws OutOfResourcesException {  
  5.     if (DEBUG_RELEASE) {  
  6.         mCreationStack = new Exception();  
  7.     }  
  8.     mCanvas = new CompatibleCanvas();  
  9.     init(s,pid,name,display,w,h,format,flags);  
  10.     mName = name;  
  11. }  

       这个构造函数,不同于我们在ViewRootImpl中看到的Surface的构造函数,这个构造函数并不是一个空壳,它做了本地实体的初始化工作,因此这个Surface才是一个真正的Suface。

       Native函数init(Surface_init@android_view_Surface.cpp)会调到SurfaceComposerClient::createSurface,再向下的过程在上一节的图中描述很清楚了,在此不作介绍了。同时,先不管SurfaceFlinger为SurfaceComposerClient创建的Surface到底是一个什么东西,我们先看看SurfaceComposerClient为WMS创建的是一个什么东西?

@SurfaceComposerClient.cpp

[cpp]  view plain copy
  1. sp<SurfaceControl> SurfaceComposerClient::createSurface(  
  2.         const String8& name,  
  3.         DisplayID display,  
  4.         uint32_t w,  
  5.         uint32_t h,  
  6.         PixelFormat format,  
  7.         uint32_t flags)  
  8. {  
  9.     sp<SurfaceControl> result;  
  10.     if (mStatus == NO_ERROR) {  
  11.         ISurfaceComposerClient::surface_data_t data;  
  12.         sp<ISurface> surface = mClient->createSurface(&data, name, //mClient为BpSurfaceComposerClient  
  13.                 display, w, h, format, flags);  
  14.         if (surface != 0) {  
  15.             result = new SurfaceControl(this, surface, data);  
  16.         }  
  17.     }  
  18.     return result;  
  19. }  

       从上面的代码我们可以看出,SurfaceComposerClient为WMS返回的是一个SurfaceControl对象,这个SurfaceControl对象包含了surfaceFlinger为SurfaceComposerClient创建的surface,这个surfaceFlinge创建的Surface在Client端的形态为ISurface。这个过程下面分析SurfaceFlinger端的Surface形态时会看到。

    SurfaceControl类中还有一个非常重要的成员mSurfaceData<class Surface : public SurfaceTextureClient>,它的类型也叫做Surface,定义在frameworks/base/include/surfaceflinger/surface.h。这个Surface提供了显示Buffer的管理。在文章的后面再介绍。

@frameworks/base/libs/gui/Surface.cpp

[cpp]  view plain copy
  1. sp<Surface> SurfaceControl::getSurface() const  
  2. {  
  3.     Mutex::Autolock _l(mLock);  
  4.     if (mSurfaceData == 0) {  
  5.         sp<SurfaceControl> surface_control(const_cast<SurfaceControl*>(this));  
  6.         mSurfaceData = new Surface(surface_control);  
  7.     }  
  8.     return mSurfaceData;  
  9. }  

1.3.2 SurfaceFlinger端Surface形态

SurfaceFlinger::createSurface@SurfaceFlinger.cpp  
[cpp]  view plain copy
  1. sp<ISurface> SurfaceFlinger::createSurface(  
  2.         ISurfaceComposerClient::surface_data_t* params,  
  3.         const String8& name,  
  4.         const sp<Client>& client,  
  5.         DisplayID d, uint32_t w, uint32_t h, PixelFormat format,  
  6.         uint32_t flags)  
  7. {  
  8.     sp<LayerBaseClient> layer;  
  9.     sp<ISurface> surfaceHandle;  
  10.   
  11.     if (int32_t(w|h) < 0) {  
  12.         LOGE("createSurface() failed, w or h is negative (w=%d, h=%d)",  
  13.                 int(w), int(h));  
  14.         return surfaceHandle;  
  15.     }  
  16.   
  17.     //LOGD("createSurface for pid %d (%d x %d)", pid, w, h);  
  18.     sp<Layer> normalLayer;  
  19.     switch (flags & eFXSurfaceMask) {  
  20.         case eFXSurfaceNormal:  
  21.             normalLayer = createNormalSurface(client, d, w, h, flags, format);  
  22.             layer = normalLayer;  
  23.             break;  
  24.         case eFXSurfaceBlur:  
  25.             // for now we treat Blur as Dim, until we can implement it  
  26.             // efficiently.  
  27.         case eFXSurfaceDim:  
  28.             layer = createDimSurface(client, d, w, h, flags);  
  29.             break;  
  30.         case eFXSurfaceScreenshot:  
  31.             layer = createScreenshotSurface(client, d, w, h, flags);  
  32.             break;  
  33.     }  
  34.   
  35.     if (layer != 0) {  
  36.         layer->initStates(w, h, flags);  
  37.         layer->setName(name);  
  38.         ssize_t token = addClientLayer(client, layer);  
  39.   
  40.         surfaceHandle = layer->getSurface();  
  41.         if (surfaceHandle != 0) {  
  42.             params->token = token;  
  43.             params->identity = layer->getIdentity();  
  44.             if (normalLayer != 0) {  
  45.                 Mutex::Autolock _l(mStateLock);  
  46.                 mLayerMap.add(layer->getSurfaceBinder(), normalLayer);  
  47.             }  
  48.         }  
  49.   
  50.         setTransactionFlags(eTransactionNeeded);  
  51.     }  
  52.   
  53.     return surfaceHandle;  
  54. }  

       当client请求SurfaceFlinger创建Surface时,SurfaceFlinger首先根据WMS提供的窗口的属性来一个命名为Layer概念的对象,然后再根据Layer创建它的子类对象LayerBaseClient::BSurface。此时第三个名为Surface(BSurface)类出现了,下一节我们来介绍一下这个Layer的概念。

 

 1.4 Layer 


1.4.1 Layer的分类

    目前,android4.0中有3中Layer类型,如上图所示。  

    1. Layer, 普通的Layer,它为每个Client端请求的Surface创建显示Buffer。

    2. LayerDim,这种Layer不会创建显示Buffer,它只是将通过这个Layer将原来FrameBuffer上的数据进行暗淡处理;

    3. LayerScreenshot,这种Layer不会创建显示Buffer,它只是将通过这个Layer将原来FrameBuffer上的数据进行抓取;

     从这些Layer看出,我们分析的重点就是第一种Layer,下面我们着重分析一下普通的Layer。Layer的具体业务我们在下一篇文章中分析

1.4.2 Layer的管理

    上文我们在分析SurfaceSession的时候,也分析过,一个Client可能会创建多个Surface,也就是要创建多个Layer,那么SurfaceFlinger端如何管理多个Layer呢?SurfaceFlinger维护了3个Vector来管理Layer<Client: DefaultKeyedVector< size_t, wp<LayerBaseClient> > mLayers;SurfaceFlinger:LayerVector     layersSortedByZ;>。

       第一种方式,我们知道SurfaceFlinger会为每个SurfaceSession创建一个Client对象,这第一种方式就是将所有为某一个SurfacSession创建的Layer保存在它对应的Client对象中。

     SurfaceFlinger::createSurface()@SurfaceFlinger.cpp,调用路径如下:

     SurfaceFlinger::addClientLayer->

         client->attachLayer(lbc)->

              mLayers.add(name, layer);

       第二种方式,在SurfaceFlinger中以排序的方式保存下来。其调用路径如下:

       SurfaceFlinger::addClientLayer->

          SurfaceFlinger::addLayer_l->

             mCurrentState.layersSortedByZ.add(layer)

       第三种方式,将所有的创建的普通的Layer保存起来,以便Client Surface在请求实现Buffer时能够辨识Client Surface对应的Layer。

SurfaceFlinger::createSurface()@SurfaceFlinger.cpp

[cpp]  view plain copy
  1. surfaceHandle = layer->getSurface();  
  2. if (surfaceHandle != 0) {  
  3.     params->token = token;  
  4.     params->identity = layer->getIdentity();  
  5.     if (normalLayer != 0) {  
  6.         Mutex::Autolock _l(mStateLock);  
  7.         mLayerMap.add(layer->getSurfaceBinder(), normalLayer);  
  8.     }  
  9. }  

2. Surface 显示Buffer的存储管理

       在前文介绍Client端的Surface形态的内容时,我们提到SurfaceControl中还会维护一个名为Surface对象,它定义在 frameworks/base/libs/surfaceflinger/Surface.h中,它负责向LayerBaseClient::BSurface请求显示Buffer,同时将显示Buffer交给JAVA Surface的Canvas去绘制窗口,我们称这个Surface为Client Surface

2.1 窗口绘制

    我们先从ViewRootImpl中分析一下,它是如何显示窗口View的,如何用到Client Surface请求的显示Buffer的。

draw()@ViewRoot.java

[cpp]  view plain copy
  1. Canvas canvas;  
  2. try {  
  3.     int left = dirty.left;  
  4.     int top = dirty.top;  
  5.     int right = dirty.right;  
  6.     int bottom = dirty.bottom;  
  7.   
  8.     final long lockCanvasStartTime;  
  9.     if (ViewDebug.DEBUG_LATENCY) {  
  10.         lockCanvasStartTime = System.nanoTime();  
  11.     }  
  12.   
  13.     canvas = surface.lockCanvas(dirty);  
  14.   
  15.     if (ViewDebug.DEBUG_LATENCY) {  
  16.         long now = System.nanoTime();  
  17.         Log.d(TAG, "Latency: Spent "  
  18.                 + ((now - lockCanvasStartTime) * 0.000001f)  
  19.                 + "ms waiting for surface.lockCanvas()");  
  20.     }  
  21.   
  22.     if (left != dirty.left || top != dirty.top || right != dirty.right ||  
  23.             bottom != dirty.bottom) {  
  24.         mAttachInfo.mIgnoreDirtyState = true;  
  25.     }  
  26.   
  27.     // TODO: Do this in native  
  28.     canvas.setDensity(mDensity);  

       上面的代码显示,JAVA Surface 会lock canvas。而Client Surface的创建就在这个过程中,即下面代码中的第一行getSurface().我们先不管Client Surface的创建,先看看Canvas是如何与Client Surface的显示Buffer关联的。

       Surface_lockCanvas@android_view_Surface.cpp

[cpp]  view plain copy
  1. static jobject Surface_lockCanvas(JNIEnv* env, jobject clazz, jobject dirtyRect)  
  2. {  
  3.     const sp<Surface>& surface(getSurface(env, clazz));  
  4.     if (!Surface::isValid(surface)) {  
  5.         doThrowIAE(env);  
  6.         return 0;  
  7.     }  
  8.   
  9.     // get dirty region  
  10.     Region dirtyRegion;  
  11.     if (dirtyRect) {  
  12.         Rect dirty;  
  13.         dirty.left  = env->GetIntField(dirtyRect, ro.l);  
  14.         dirty.top   = env->GetIntField(dirtyRect, ro.t);  
  15.         dirty.right = env->GetIntField(dirtyRect, ro.r);  
  16.         dirty.bottom= env->GetIntField(dirtyRect, ro.b);  
  17.         if (!dirty.isEmpty()) {  
  18.             dirtyRegion.set(dirty);  
  19.         }  
  20.     } else {  
  21.         dirtyRegion.set(Rect(0x3FFF,0x3FFF));  
  22.     }  
  23.   
  24.     Surface::SurfaceInfo info;  
  25.     status_t err = surface->lock(&info, &dirtyRegion);  
  26.     if (err < 0) {  
  27.         const charconst exception = (err == NO_MEMORY) ?  
  28.             OutOfResourcesException :  
  29.             "java/lang/IllegalArgumentException";  
  30.         jniThrowException(env, exception, NULL);  
  31.         return 0;  
  32.     }  
  33.   
  34.     // Associate a SkCanvas object to this surface  
  35.     jobject canvas = env->GetObjectField(clazz, so.canvas);  
  36.     env->SetIntField(canvas, co.surfaceFormat, info.format);  
  37.   
  38.     SkCanvas* nativeCanvas = (SkCanvas*)env->GetIntField(canvas, no.native_canvas);  
  39.     SkBitmap bitmap;  
  40.     ssize_t bpr = info.s * bytesPerPixel(info.format);  
  41.     bitmap.setConfig(convertPixelFormat(info.format), info.w, info.h, bpr);  
  42.     if (info.format == PIXEL_FORMAT_RGBX_8888) {  
  43.         bitmap.setIsOpaque(true);  
  44.     }  
  45.     if (info.w > 0 && info.h > 0) {  
  46.         bitmap.setPixels(info.bits);  
  47.     } else {  
  48.         // be safe with an empty bitmap.  
  49.         bitmap.setPixels(NULL);  
  50.     }  
  51.     nativeCanvas->setBitmapDevice(bitmap);  
  52.   
  53.     SkRegion clipReg;  
  54.     if (dirtyRegion.isRect()) { // very common case  
  55.         const Rect b(dirtyRegion.getBounds());  
  56.         clipReg.setRect(b.left, b.top, b.right, b.bottom);  
  57.     } else {  
  58.         size_t count;  
  59.         Rect const* r = dirtyRegion.getArray(&count);  
  60.         while (count) {  
  61.             clipReg.op(r->left, r->top, r->right, r->bottom, SkRegion::kUnion_Op);  
  62.             r++, count--;  
  63.         }  
  64.     }  
  65.   
  66.     nativeCanvas->clipRegion(clipReg);  
  67.   
  68.     int saveCount = nativeCanvas->save();  
  69.     env->SetIntField(clazz, so.saveCount, saveCount);  
  70.   
  71.     if (dirtyRect) {  
  72.         const Rect& bounds(dirtyRegion.getBounds());  
  73.         env->SetIntField(dirtyRect, ro.l, bounds.left);  
  74.         env->SetIntField(dirtyRect, ro.t, bounds.top);  
  75.         env->SetIntField(dirtyRect, ro.r, bounds.right);  
  76.         env->SetIntField(dirtyRect, ro.b, bounds.bottom);  
  77.     }  
  78.   
  79.     return canvas;  
  80. }  

      上面的代码,我们可以看出,Canvas的Bitmap设备设置了Client Surface的显示Buffer为其Bitmap pixel存储空间。 

[cpp]  view plain copy
  1. bitmap.setPixels(info.bits);  

    这样Canvas的绘制空间就有了。下一步就该绘制窗口了。

   draw()@ViewRootImpl.java

[cpp]  view plain copy
  1. try {  
  2.       canvas.translate(0, -yoff);  
  3.       if (mTranslator != null) {  
  4.           mTranslator.translateCanvas(canvas);  
  5.       }  
  6.       canvas.setScreenDensity(scalingRequired  
  7.               ? DisplayMetrics.DENSITY_DEVICE : 0);  
  8.       mAttachInfo.mSetIgnoreDirtyState = false;  
  9.       mView.draw(canvas);  
  10.   }  


    其中ViewRootImpl中的mView为整个窗口的View。它将Render自己和所有它的子View。

2.2 Client Surface的初始化(SurfaceControl中的Surface)

        Client Surface的创建是从ViewRootImpl首次Lock canvas时进行的,这么做的目的可能也是为了节约空间,减少不必要的开支。

        Client Surface的初始化和显示Buffer的管理过程比较复杂,下图给出了这一部分的一个静态结构图,有些东西从图上表现不出来,下面我简单的介绍一下。

 

framework是如何与surfaceflinger进行业务交互的。

       1)如何创建surface

       2)如何显示窗口等等

       所有的这一切都是通过系统服务WindowManagerService与surfaceflinger来进行的。

        Android中的Surface机制这一块代码写的比较难理解,光叫Surface的类就有3个,因此本篇文章从两部分来分析。

       首先,想要理解Surface机制,还是需要首先理清各个类之间的关系。

       其次,在理解了整个Surface机制的类关系之后,到时我们再结合前一篇文章中对显示系统的介绍,研究一下一个Surface是如何和显示系统建立起联系来的,这个联系主要是指Surface的显示buffer的存储管理。

在下篇文章中,再分析SurfaceFlinger是如何将已经存储了窗口图形数据的Surface Buffer显示到显示系统中。

待续。。。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值