Surface绘图缓冲区的创建流程

839 阅读15分钟

Android View绘制是GUI系统的核心,而绘制view是需要缓冲区的,也就是我们说的画布,因此了解这个缓冲区的分配流程是有必要的,本篇将对该缓冲区的分配进行解释。

一、Activity结构剖析

Acitivty实际上在WMS端只是个Window,是以WindowState进行描述的,在AMS端它是一个ActivityRecord,在Activity内部它持有一个mWindow,它实际上为一个PhoneWindow实例,在PhoneWindow中维护了一个DecorView,也就是view树,这个PhoneWindow实例由一个WindowManagerImpl进行管理,在WindowManagaerImpl内部持有一个WindowManagerGlobal单例,它内部持有WMS的本地代理IWindowManager和由其打开的一个IWindowSession负责和WMS进行会话,另一方面它负责整个应用的窗口视图的管理,也就是DecorView及ViewRootImpl的管理。每个新添加的window最终会在WMS端以WidowState的形式存在于WMS,WMS不关心window的View树的内容,它只关心Window的大小样式以及Z序等,而绘制的流程是由我们应用程序进行的,实际上就是由ViewRootImp进行绘制的。那么相应的ViewRootImpl在进行绘制前是需要一个画布进行view树的绘制的,这个画布就是Surface。接下来我们将围绕这个Surface进行话题的展开。

二、画布的分配

在ViewRootImpl创建时同时会new一个Surface对象

 private final Surface mSurface = new Surface();

接下来我们看下这个Surface的内部会做些什么。

public class Surface implements Parcelable {
    ^
    int mNativeObject; // package scope only for SurfaceControl access
    private int mLockedObject;
    private int mGenerationId; // incremented each time mNativeObject changes
    private final Canvas mCanvas = new CompatibleCanvas();
    ……
    public Surface() {
    }
    ……
}

可以看到Surface的构造方法只是个空实现,而貌似mCanvas可能会是真正的画布,我们继续看看Canvas的代码

public class Canvas {
     /** @hide */
    public int mNativeCanvas;
    // may be null
    private Bitmap mBitmap;
    // optional field set by the caller
    private DrawFilter mDrawFilter;
    ……
    public Canvas() {
        if (!isHardwareAccelerated()) {
            // 0 means no native bitmap
            mNativeCanvas = initRaster(0);
            mFinalizer = new CanvasFinalizer(mNativeCanvas);
        } else {
            mFinalizer = null;
        }
    }
    ……
}

在Canava的构造方法中也并没有相关缓冲区分配的动作,这么说new出来的Surface并非真的分派了缓冲区,而只是一个空壳。想想也就能理解,我们知道ViewRootImpl分派的时机是WindowManagerGlobal通过addView来添加view树的时候分配的时候,这时候WMS还不知道这个Window的存在的(最起码得知道分配多大吧),那么给view树分配缓冲区的确为时过早。那么什么时候分配合适呢?当然是准备绘制view树的时候。view树的绘制是在performTraversal中进行的。

private void performTraversals() {
    // cache mView since it is used so much below...
    final View host = mView;//viewRoot管理的view树 decorView
    ……
    boolean windowShouldResize = layoutRequested && windowSizeMayChange
            && ((mWidth != host.getMeasuredWidth() || mHeight != host.getMeasuredHeight())
                || (lp.width == ViewGroup.LayoutParams.WRAP_CONTENT &&
                        frame.width() < desiredWindowWidth && frame.width() != mWidth)
                || (lp.height == ViewGroup.LayoutParams.WRAP_CONTENT &&
                        frame.height() < desiredWindowHeight && frame.height() != mHeight));
    ……
    if (mFirst || windowShouldResize || insetsChanged ||
                viewVisibilityChanged || params != null || mConfigurationChanged) {
         relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
         ……
    }
    ……
    performMeasure();
    ……
    performLayout();
    ……
    performDraw();
}

performTraversals函数比较长,我这里只取跟本篇相关的内容,在performTraversals并非仅仅只有三大绘制流程performMeasure,performLayout和performDraw,实际上在这三个流程之前还是做了很多事情的,我简单的说下:

  1. 计算期望的窗口大小,如果Window带状态栏,那么在其大小中应该除去状态栏的那部分宽高。否则大小应该为整个屏幕的大小

  2. 如果窗口大小发生了变化也需要记录下来

  3. 计算窗口的内容区域边衬是否变化

  4. 如果可见性发生了变化也需要记录,同时通知view树子视图可见性发生了变化

  5. 根据条件判断是否需要relayoutWindow,在relayoutWindow中会重新计算窗口大小。需要满足的条件至少为以下一种:

     <1>. Activity窗口是第一次执行测量、布局和绘制操作,即ViewRoot类的成员变量mFirst的值等于true。
     
     <2>. 前面得到的变量windowShouldResize的值等于true,即Activity窗口的大小的确是发生了变化。
     
     <3>. 前面得到的变量insetsChanged的值等于true,即Activity窗口的内容区域边衬发生了变化。
     
     <4>. Activity窗口的可见性发生了变化,即变量viewVisibilityChanged的值等于true。
     
     <5>. Activity窗口的属性发生了变化,即变量params指向了一个WindowManager.LayoutParams对象
    

6.执行绘制流程,这个在另外的篇幅再做介绍

在relayoutWindow中会计算窗口的大小,同时这里会为窗口分配缓冲区。

private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,
            boolean insetsPending) throws RemoteException {

    ……
    int relayoutResult = mWindowSession.relayout(
            mWindow, mSeq, params,
            (int) (mView.getMeasuredWidth() * appScale + 0.5f),
            (int) (mView.getMeasuredHeight() * appScale + 0.5f),
            viewVisibility, insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0,
            mWinFrame, mPendingOverscanInsets, mPendingContentInsets, mPendingVisibleInsets,
            mPendingConfiguration, mSurface);

    ……
    return relayoutResult;
}

通过mWindowSession和WMS进行会话调用relayout计算窗口的大小并将mSurface传递给WMS。IWindowSession的服务端为Session,我们看看它的实现

public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs,
        int requestedWidth, int requestedHeight, int viewFlags,
        int flags, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
        Rect outVisibleInsets, Configuration outConfig, Surface outSurface) {
    int res = mService.relayoutWindow(this, window, seq, attrs,
            requestedWidth, requestedHeight, viewFlags, flags,
            outFrame, outOverscanInsets, outContentInsets, outVisibleInsets,
            outConfig, outSurface);//调用WMS的relayoutWindow
    return res;
}

Session的relayout会通过WMS的relayoutWindow来完成。

public int relayoutWindow(Session session, IWindow client, int seq,
    WindowManager.LayoutParams attrs, int requestedWidth,
    int requestedHeight, int viewVisibility, int flags,
    Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
    Rect outVisibleInsets, Configuration outConfig, Surface outSurface) {

    synchronized(mWindowMap) {
        WindowState win = windowForClientLocked(session, client, false);
        if (win == null) {
            return 0;
        }
        WindowStateAnimator winAnimator = win.mWinAnimator;

        ……
        try {
            if (!win.mHasSurface) {
                surfaceChanged = true;
            }
            //创建SurfaceControl 准备画布
            SurfaceControl surfaceControl = winAnimator.createSurfaceLocked();
            if (surfaceControl != null) {
                outSurface.copyFrom(surfaceControl);
            } else {
                // For some reason there isn't a surface.  Clear the
                // caller's object so they see the same state.
                outSurface.release();
            }
        } 
        ……
    }

}

relayoutWindow的参树client为ViewRootImpl传递的W对象,是一个Binder对象,WMS通过client来通知应用窗口的变化。最后一个参数从命名上来看,它是一个出参,也就是通过这个方法可以拿到真正可用的Surface。可以看到outSurface是由copyFrom从SurfaceControl得来的。这个surfaceControl是通过winAnimator.createSurfaceLocked()来创建的。这个winAnimator是一个WindowStateAnimator,在我们为Window创建WindowState时创建的,它和WindowState是一一对应的。

frameworks/base/services/java/com/android/server/wm/WindowStateAnimator.java
SurfaceControl createSurfaceLocked() {
    if (mSurfaceControl == null) {
        ……
        mSurfaceControl = new SurfaceControl(
            mSession.mSurfaceSession,
            attrs.getTitle().toString(),
            w, h, format, flags);
        ……
    }
    return mSurfaceControl;
}

mSurfaceControl在WindowStateAnimator中只会创建一次,这里的mSession实际上就是应用端和WMS进行会话的session,即IWindowSession,在创建时会指定缓冲区大小,格式以及标记。那么mSurfaceSession是什么呢,在哪里创建的呢?我们继续看

frameworks/base/services/java/com/android/server/wm/WindowManagerService.java
 //为客户端创建一个Session会话,后面客户端使用这个Session同WMS进行会话    
@Override
public IWindowSession openSession(IInputMethodClient client,
        IInputContext inputContext) {
    Session session = new Session(this, client, inputContext);
    return session;
}

public int addWindow(Session session, IWindow client, int seq,
    WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
    Rect outContentInsets, InputChannel outInputChannel) {
    ……    
    win = new WindowState(this, session, client, token,
                    attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent);
    ……
    win.attach()
    ……
}
frameworks/base/services/java/com/android/server/wm/WindowState.java
void attach() {
    if (WindowManagerService.localLOGV) Slog.v(
        TAG, "Attaching " + this + " token=" + mToken
        + ", list=" + mToken.windows);
    mSession.windowAddedLocked();
}
frameworks/base/services/java/com/android/server/wm/Session.java
void windowAddedLocked() {
    if (mSurfaceSession == null) {
        mSurfaceSession = new SurfaceSession();
        mService.mSessions.add(this);
    }
    mNumWindow++;
}

在WMS为应用打开一个会话session后并没有立马去创建mSurfaceSession,而是在Window添加到WMS的时候创建完WindowState后通过attach方法创建的。它同样的对于一个Session只会创建一个,也就是说我们的应用程序只会有一个SurfaceSession,因为它是Session的成员嘛。

public final class SurfaceSession {
    // Note: This field is accessed by native code.
    private int mNativeClient; // SurfaceComposerClient*

    private static native int nativeCreate();
    private static native void nativeDestroy(int ptr);
    private static native void nativeKill(int ptr);

    /** Create a new connection with the surface flinger. */
    public SurfaceSession() {
        mNativeClient = nativeCreate();
    }

    ……
}

SurfaceSession的实现很简单,因为它的工作都放在native层完成了。

frameworks/base/core/jni/android_view_SurfaceSession.cpp
static jint nativeCreate(JNIEnv* env, jclass clazz) {
    SurfaceComposerClient* client = new SurfaceComposerClient();//SurfaceComposerClient是处于客户端的
    client->incStrong((void*)nativeCreate);
    return reinterpret_cast<jint>(client);
}

实际上它是创建了一个SurfaceComposerClient对象并放在mNativeClient中。这个对象是用来和SurfaceFlinger打交道的,但它并不是SurfaceFlinger的本地代理。SurfaceFlinger负责界面图层的合成,这之间会涉及我们的缓冲区,所以分配缓冲区的工作需要经过SurfaceFlinger来进行。

弄清楚SurfaceSession是什么后,接下来我们看SurfaceControl的创建,它会用到SurfaceSession。

public class SurfaceControl {
    int mNativeObject;
    public SurfaceControl(SurfaceSession session,
            String name, int w, int h, int format, int flags)
                    throws OutOfResourcesException {
        mName = name;
        mNativeObject = nativeCreate(session, name, w, h, format, flags);//通过native层创建SurfaceControl
    }
}

同样的,它的工作也是在native层进行的。

frameworks/base/core/jni/android_view_SurfaceControl.cpp
static jint nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj,
        jstring nameStr, jint w, jint h, jint format, jint flags) {
    ScopedUtfChars name(env, nameStr);
    sp<SurfaceComposerClient> client(android_view_SurfaceSession_getClient(env, sessionObj));
    sp<SurfaceControl> surface = client->createSurface(
            String8(name.c_str()), w, h, format, flags);//创建SurfaceHolder
    if (surface == NULL) {
        jniThrowException(env, OutOfResourcesException, NULL);
        return 0;
    }
    surface->incStrong((void *)nativeCreate);
    return int(surface.get());//这里返回创建的SurfaceControl
}
frameworks/base/core/jni/android_view_SurfaceSession.cpp
sp<SurfaceComposerClient> android_view_SurfaceSession_getClient(
        JNIEnv* env, jobject surfaceSessionObj) {
    return reinterpret_cast<SurfaceComposerClient*>(
            env->GetIntField(surfaceSessionObj, gSurfaceSessionClassInfo.mNativeClient));
}

在nativeCreate中首先通过android_view_SurfaceSession_getClient从SurfaceSession中取到之前创建的SurfaceComoserClient对象,然后通过该对象调用的CreateSurface创建SurfaceControl。

/frameworks/native/libs/gui/SurfaceComposerClient.cpp
void SurfaceComposerClient::onFirstRef() {
    sp<ISurfaceComposer> sm(ComposerService::getComposerService());
    if (sm != 0) {
        sp<ISurfaceComposerClient> conn = sm->createConnection();//与surfaceflinger建立连接
        if (conn != 0) {
            mClient = conn;//mClient对应服务端Client
            mStatus = NO_ERROR;
        }
    }
}

sp<ISurfaceComposer> ComposerService::getComposerService() {
    ComposerService& instance = ComposerService::getInstance();//实例采用单例
    Mutex::Autolock _l(instance.mLock);
    if (instance.mComposerService == NULL) {
        ComposerService::getInstance().connectLocked();
        assert(instance.mComposerService != NULL);
        ALOGD("ComposerService reconnected");
    }
    return instance.mComposerService;
}
void ComposerService::connectLocked() {
    const String16 name("SurfaceFlinger");
    while (getService(name, &mComposerService) != NO_ERROR) {//获取surfaceflinger服务
        usleep(250000);
    }
    ……
}

sp<SurfaceControl> SurfaceComposerClient::createSurface(
        const String8& name,
        uint32_t w,
        uint32_t h,
        PixelFormat format,
        uint32_t flags)
{
    sp<SurfaceControl> sur;
    if (mStatus == NO_ERROR) {
        sp<IBinder> handle;
        sp<IGraphicBufferProducer> gbp;
        status_t err = mClient->createSurface(name, w, h, format, flags,
                &handle, &gbp);//在Client服务端创建相应的Layer
        ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err));
        if (err == NO_ERROR) {
            sur = new SurfaceControl(this, handle, gbp);//同时创建一个SurfaceControl,这个gbp即是对应Layer的BufferQueue
        }
    }
    return sur;
}

SurfaceComposerClient在创建完后,强引用的会首先会执行onFirstRef 在这个方法里会通过 ComposerService::getComposerService获取到SurfaceFlinger的Binder本地代理sm,这是在ComposerService::connectLocked中通过getService获取的,SurfaceFlinger是实名Binder,因此可以通过ServiceManager查询得到。获取到SurfaceFlinger的本地代理后,就可以通过createConnection创建ISurfaceComposerClient,它是一个匿名Binder,是SurfaceFlinger服务中Client 的本地代理。Client也是个Binder Server,SurfaceFlinger为每个于其建立连接的应用进程维护一个Client便于管理。

frameworks/native/services/surfaceflinger/Client.cpp
//应用程序创建Surface
status_t Client::createSurface(
        const String8& name,
        uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
        sp<IBinder>* handle,
        sp<IGraphicBufferProducer>* gbp)
{
    class MessageCreateLayer : public MessageBase {
        SurfaceFlinger* flinger;
        Client* client;
        sp<IBinder>* handle;
        sp<IGraphicBufferProducer>* gbp;
        status_t result;
        const String8& name;
        uint32_t w, h;
        PixelFormat format;
        uint32_t flags;
    public:
        MessageCreateLayer(SurfaceFlinger* flinger,
                const String8& name, Client* client,
                uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
                sp<IBinder>* handle,
                sp<IGraphicBufferProducer>* gbp)
            : flinger(flinger), client(client),
              handle(handle), gbp(gbp),
              name(name), w(w), h(h), format(format), flags(flags) {
        }
        status_t getResult() const { return result; }
        //message最终通过这个handler进行处理
        virtual bool handler() {
            result = flinger->createLayer(name, client, w, h, format, flags,
                    handle, gbp);//创建过程由sf的createLayer完成,客户端创建一个Surface,对应的在sf中创建一个Layer
            return true;
        }
    };

    sp<MessageBase> msg = new MessageCreateLayer(mFlinger.get(),
            name, this, w, h, format, flags, handle, gbp);
    mFlinger->postMessageSync(msg);//通过消息队列的方式来处理请求,主要是因为sf是为多个应用服务的,用这样的方式便于处理多个请求。
    return static_cast<MessageCreateLayer*>( msg.get() )->getResult();
}

在Client中createSurfac会通过请求参数构造一个MessageBase然后post到SurfaceFlinger的MessageQueue,最终事件会通过MessageBase的handleMessage进行处理,在handleMessage中调用了虚方法handler进行消息的处理。也就是MessageCreateLayer的handler进行处理。

void MessageBase::handleMessage(const Message&) {
    this->handler();//调用handler方法
    barrier.open();
};

在MessageCreateLayer的handler中又会通过SurfaceFlinger的createLayout为客户端创建一个Layer,这个Layer即图层,它对应于应用端的Window。

status_t SurfaceFlinger::createLayer(
    const String8& name,
    const sp<Client>& client,
    uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
    sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp)//为客户端创建Layer
{
    ……
    sp<Layer> layer;

    switch (flags & ISurfaceComposerClient::eFXSurfaceMask) {//支持两种类型的Layer Normal和Dim
        case ISurfaceComposerClient::eFXSurfaceNormal:
            result = createNormalLayer(client,
                    name, w, h, flags, format,
                    handle, gbp, &layer);
            break;
        case ISurfaceComposerClient::eFXSurfaceDim:
            result = createDimLayer(client,
                    name, w, h, flags,
                    handle, gbp, &layer);
            break;
        default:
            result = BAD_VALUE;
            break;
    }

    if (result == NO_ERROR) {
        addClientLayer(client, *handle, *gbp, layer);//将创建的Layer添加到用户的队列中
        setTransactionFlags(eTransactionNeeded);
    }
    return result;
}

在SurfaceFlinger的createLayer中会根据flag来创建不同的layer,分别为Normal和Dim类型的,创建完layer后会将其添加到client中去。这里我们看下CreateNormalLayer的实现即可。

status_t SurfaceFlinger::createNormalLayer(const sp<Client>& client,
        const String8& name, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format,
        sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer)//创建Normal类型的Layer
{
    // initialize the surfaces
    switch (format) {
        case PIXEL_FORMAT_TRANSPARENT:
        case PIXEL_FORMAT_TRANSLUCENT:
            format = PIXEL_FORMAT_RGBA_8888;
            break;
        case PIXEL_FORMAT_OPAQUE:
    #ifdef NO_RGBX_8888
            format = PIXEL_FORMAT_RGB_565;
    #else
            format = PIXEL_FORMAT_RGBX_8888;
    #endif
            break;
    }

#ifdef NO_RGBX_8888
    if (format == PIXEL_FORMAT_RGBX_8888)
        format = PIXEL_FORMAT_RGBA_8888;
#endif

    *outLayer = new Layer(this, client, name, w, h, flags);//创建Layouer 在第一次引用该Layer时会创建其BufferQueue和Consumer
    status_t err = (*outLayer)->setBuffers(w, h, format, flags);//设置layer大小和格式
    if (err == NO_ERROR) {
        *handle = (*outLayer)->getHandle();
        *gbp = (*outLayer)->getBufferQueue();//获取Layer对应的BufferQueue
    }
    return err;
}

创建Layer的实例后就可以通过getBufferQueue获取到layer内部的BufferQueue,这个BufferQueue是个Binder Server,它是一个缓冲队列,用来维护layer的缓冲区。它是在Layer的onFirstRef中创建的,我们缓冲区的分配在SurfaceFligner端实际实际上就是通过它来分配的。同时,它既是缓冲区的消费者又是生产者,对于应用端来说,它扮演生产者的角色,因为应用端是填充数据的一方,而对于surfaceFligner来说它又扮演消费者的角色,因为SurfaceFlinger是合成layer层,取出缓冲区进行显示的。

void Layer::onFirstRef() {//在第一次引用时创建一个bufferqueue
    // Creates a custom BufferQueue for SurfaceFlingerConsumer to use
    mBufferQueue = new SurfaceTextureLayer(mFlinger);//创建一个BufferQueue用于管理Layer的图形缓冲区
    ……  
}

class SurfaceTextureLayer : public BufferQueue {//父类是BufferQueue
    sp<SurfaceFlinger> flinger;
public:
    SurfaceTextureLayer(const sp<SurfaceFlinger>& flinger);
    virtual ~SurfaceTextureLayer();
};

这里的SurfaceTextureLayer它实际上就是个BufferQueue。

sp<SurfaceControl> SurfaceComposerClient::createSurface(
        const String8& name,
        uint32_t w,
        uint32_t h,
        PixelFormat format,
        uint32_t flags)
{
    sp<SurfaceControl> sur;
    if (mStatus == NO_ERROR) {
        sp<IBinder> handle;
        sp<IGraphicBufferProducer> gbp;
        status_t err = mClient->createSurface(name, w, h, format, flags,
                &handle, &gbp);//在Client服务端创建相应的Layer
        ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err));
        if (err == NO_ERROR) {
            sur = new SurfaceControl(this, handle, gbp);//同时创建一个SurfaceControl,这个gbp即是对应Layer的BufferQueue
        }
    }
    return sur;
}

我们创建好layer后通过getBufferQueue后是以IGraphicBufferProducer的角色返回的,它代表了这个BufferQueue将作为一个生产者供应用端使用。紧接着在本地创建一个SurfaceControl 需要注意这个时候gbd是在我们的应用进程中了,它是BufferQueue的本地代理binder对象了。 我们通过这个代理对象来创建SurfaceControl。

SurfaceControl::SurfaceControl(
        const sp<SurfaceComposerClient>& client,
        const sp<IBinder>& handle,
        const sp<IGraphicBufferProducer>& gbp)
    : mClient(client), mHandle(handle), mGraphicBufferProducer(gbp)
{
}

这里我们创建好本地的SurfaceControl,然后保存在java层的SurfaceControl的mNativeObject中。但是这个时候好像并没有真正去分配缓冲区,那么创建这个SurfaceControl给上层到底是干嘛用的?没错,就是用来分配缓冲区的,因为它内部这时候是有一个IGraphicBufferProducer的,它是layer中的BufferQueue代理binder。

在WMS的relayoutWindow中创建完SurfaceControl后,会通过Surface的copyFrom来初始化它,在这之前Surface还是个空壳。

public class Surface implements Parcelable {
    ……
    public void copyFrom(SurfaceControl other) {
        if (other == null) {
            throw new IllegalArgumentException("other must not be null");
        }

        int surfaceControlPtr = other.mNativeObject;//取到指向SurfaceControl的本地对象指针
        if (surfaceControlPtr == 0) {
            throw new NullPointerException(
                    "SurfaceControl native object is null. Are you using a released SurfaceControl?");
        }
        int newNativeObject = nativeCreateFromSurfaceControl(surfaceControlPtr);//通过SurfaceControl来创建新的Surface

        synchronized (mLock) {
            if (mNativeObject != 0) {
                nativeRelease(mNativeObject);
            }
            setNativeObjectLocked(newNativeObject);
        }
    }
    ……
}

java层的Surface是通过nativeCreateFromSurfaceControl,并将native层的SurfaceControl对象指针传递给它。

static jint nativeCreateFromSurfaceControl(JNIEnv* env, jclass clazz,
        jint surfaceControlNativeObj) {
    sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(surfaceControlNativeObj));
    sp<Surface> surface(ctrl->getSurface());//返回surfacecontrol管理的surface
    if (surface != NULL) {
        surface->incStrong(&sRefBaseOwner);
    }
    return reinterpret_cast<jint>(surface.get());
}

通过native层的SurfaceControl指针,可以通过getSurface获取到一个Surface。

sp<Surface> SurfaceControl::getSurface() const//获取内部持有的Surface
{
    Mutex::Autolock _l(mLock);
    if (mSurfaceData == 0) {//第一次为空时创建
        // This surface is always consumed by SurfaceFlinger, so the
        // producerControlledByApp value doesn't matter; using false.
        mSurfaceData = new Surface(mGraphicBufferProducer, false);//这个surface是sf中消费的。
    }
    return mSurfaceData;
}

private void setNativeObjectLocked(int ptr) {
    if (mNativeObject != ptr) {
        if (mNativeObject == 0 && ptr != 0) {
            mCloseGuard.open("release");
        } else if (mNativeObject != 0 && ptr == 0) {
            mCloseGuard.close();
        }
        mNativeObject = ptr;
        mGenerationId += 1;
    }
}

SurfaceControl 并不直接去分配缓冲区,而是通过管理一个本地Surface对象来管理缓冲区,它通过mGraphicBufferProducer构造,这个就是之前我们取到的IGraphicBufferProducer binder代理对象,构造的本地Surface最终会通过setNativeObjectLocked 保存在java层Surface的mNativeObject中。到这里java层的Surface就算创建完了,最终返回给ViewRootImpl使用。

三、Surface的使用

3.1 从Surface中取缓冲区

private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int yoff,
            boolean scalingRequired, Rect dirty) {
    Canvas canvas;
    ……
    canvas = mSurface.lockCanvas(dirty);
    try {
        ……
        mView.draw(canvas);
    } finally {
        try {
            surface.unlockCanvasAndPost(canvas);
        } 
    }
    return true;
}

Surface首先通过lockCanvas获取到一个Canvas对象,这个Canvas实际上为就是通过Surface的缓冲区填充的画布。

public Canvas lockCanvas(Rect inOutDirty)
            throws Surface.OutOfResourcesException, IllegalArgumentException {
    synchronized (mLock) {
        ……
        mLockedObject = nativeLockCanvas(mNativeObject, mCanvas, inOutDirty);
        return mCanvas;
    }
}

//jni层的surface lockCanvas调用
static jint nativeLockCanvas(JNIEnv* env, jclass clazz,
        jint nativeObject, jobject canvasObj, jobject dirtyRectObj) {
    sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject));//这个surface由surfaceControl创建的
    if (!isSurfaceValid(surface)) {
        doThrowIAE(env);
        return 0;
    }

    Rect dirtyRect;
    Rect* dirtyRectPtr = NULL;

    if (dirtyRectObj) {
        dirtyRect.left   = env->GetIntField(dirtyRectObj, gRectClassInfo.left);
        dirtyRect.top    = env->GetIntField(dirtyRectObj, gRectClassInfo.top);
        dirtyRect.right  = env->GetIntField(dirtyRectObj, gRectClassInfo.right);
        dirtyRect.bottom = env->GetIntField(dirtyRectObj, gRectClassInfo.bottom);
        dirtyRectPtr = &dirtyRect;
    }

    ANativeWindow_Buffer outBuffer;//ANativeWindow_Buffer定义在native_window.h中
    status_t err = surface->lock(&outBuffer, dirtyRectPtr);
    if (err < 0) {
        const char* const exception = (err == NO_MEMORY) ?
                OutOfResourcesException :
                "java/lang/IllegalArgumentException";
        jniThrowException(env, exception, NULL);
        return 0;
    }

    // Associate a SkCanvas object to this surface
    env->SetIntField(canvasObj, gCanvasClassInfo.mSurfaceFormat, outBuffer.format);//将skCanvas是关联到surface
    SkBitmap bitmap;//准备画布
    ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);
    bitmap.setConfig(convertPixelFormat(outBuffer.format), outBuffer.width, outBuffer.height, bpr);//设置画布大小及格式
    if (outBuffer.format == PIXEL_FORMAT_RGBX_8888) {
        bitmap.setAlphaType(kOpaque_SkAlphaType);
    }
    if (outBuffer.width > 0 && outBuffer.height > 0) {
        bitmap.setPixels(outBuffer.bits);//给画布设置缓冲区
    } else {
        // be safe with an empty bitmap.
        bitmap.setPixels(NULL);
    }

    SkCanvas* nativeCanvas = SkNEW_ARGS(SkCanvas, (bitmap));//将画布作为native的Canvase返回给上层使用
    swapCanvasPtr(env, canvasObj, nativeCanvas);

    if (dirtyRectPtr) {
        nativeCanvas->clipRect( SkRect::Make(reinterpret_cast<const SkIRect&>(dirtyRect)) );
    }

    if (dirtyRectObj) {
        env->SetIntField(dirtyRectObj, gRectClassInfo.left,   dirtyRect.left);
        env->SetIntField(dirtyRectObj, gRectClassInfo.top,    dirtyRect.top);
        env->SetIntField(dirtyRectObj, gRectClassInfo.right,  dirtyRect.right);
        env->SetIntField(dirtyRectObj, gRectClassInfo.bottom, dirtyRect.bottom);
    }
    sp<Surface> lockedSurface(surface);
    lockedSurface->incStrong(&sRefBaseOwner);
    return (int) lockedSurface.get();
}

Surface的localCanvas是通过nativeLockCanvas,首先通过mNativeObject取到本地的Surface对象,通过这个本地的Surface进行lock取到缓冲区outBuffer,它是一个ANativeWindow_Buffer,随后通过这个缓冲区初始化一个SkBitmap画布,并设置其格式大小等,通过SkBitmap创建一个SkCanvas返回给java层Surface的mCanvas,我们在Draw方法中使用的Canvas就是这个SkCanvas.

status_t Surface::lock(
        ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds)
{
    ……
    ANativeWindowBuffer* out;// 定义在window.h
    int fenceFd = -1;
    status_t err = dequeueBuffer(&out, &fenceFd);//分配缓冲区
    ……
}

//申请图形缓冲区
int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {
    ATRACE_CALL();
    Mutex::Autolock lock(mMutex);
    int buf = -1;
    int reqW = mReqWidth ? mReqWidth : mUserWidth;
    int reqH = mReqHeight ? mReqHeight : mUserHeight;
    ……
    sp<Fence> fence;
    status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence, mSwapIntervalZero,
            reqW, reqH, mReqFormat, mReqUsage);
    ……
    sp<GraphicBuffer>& gbuf(mSlots[buf].buffer);
    ……
    if ((result & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) || gbuf == 0) {//未分配 或者需要重新映射
        result = mGraphicBufferProducer->requestBuffer(buf, &gbuf);//Surface通过调用 requestBuffer将图形缓冲区映射到Surface所在进程
        if (result != NO_ERROR) {
            ALOGE("dequeueBuffer: IGraphicBufferProducer::requestBuffer failed: %d", result);
            return result;
        }
    }
    ……
    *buffer = gbuf.get();//获取缓冲区
    return OK;
}

首先通过mGraphicBufferProducer通过dequeueBuffer分配缓冲区,实际是由BufferQueue完成的,它实际上是取到BufferQueue中BufferSlot槽的索引buf,有了这个索引,通过requestBuffer就真正的创建buffer并将该buffer映射到Surface所在进程。这样我们的应用程序就可以使用了。

3.2 提交绘制好的缓冲区

public void unlockCanvasAndPost(Canvas canvas) {
    ……
    synchronized (mLock) {
        ……
        nativeUnlockCanvasAndPost(mLockedObject, canvas);
        nativeRelease(mLockedObject);
        mLockedObject = 0;
    }
}

同样的应用层绘制完后,需要将该缓冲区unlock并且提交给BufferQueue。这个是通过nativeUnlockCanvasAndPost进行的。

static void nativeUnlockCanvasAndPost(JNIEnv* env, jclass clazz,
        jint nativeObject, jobject canvasObj) {
    sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject));
    if (!isSurfaceValid(surface)) {
        return;
    }

    // detach the canvas from the surface
    SkCanvas* nativeCanvas = SkNEW(SkCanvas);
    swapCanvasPtr(env, canvasObj, nativeCanvas);//把canvas从surface分离

    // unlock surface
    status_t err = surface->unlockAndPost();//提交结果
    if (err < 0) {
        doThrowIAE(env);
    }
}
status_t Surface::unlockAndPost()//提交Locked的Buffer
{
    if (mLockedBuffer == 0) {
        ALOGE("Surface::unlockAndPost failed, no locked buffer");
        return INVALID_OPERATION;
    }
    status_t err = mLockedBuffer->unlock();
    err = queueBuffer(mLockedBuffer.get(), -1);//将该Buffer queue
    mPostedBuffer = mLockedBuffer;//locked的buffer变为posted
    ……
    return err;
}

Surfae的unlockAndPost调用queueBuffer方法完成buffer的提交

int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) {//buffer queue进行消费
    ……
    status_t err = mGraphicBufferProducer->queueBuffer(i, input, &output);//通过调用GBP的
    ……
    return err;
}

通过mGraphicBufferProducer入队这个buffer,此时生产者的任务完毕,layer端的Consumer即SurfaceFlinger会监听到这个有效的缓冲区,然后准备合成显示layer,最终将绘制的东西显示在屏幕上。