深刻Android系统(十二)Android图形显示系统-1-显示原理与Surface

关于图形显示部分能够参考官网:Graphicsjava

图像显示原理

Linux一般使用Framebuffer来用做显示输出(Framebuffer知识详解在这里),Framebuffer就是一块内存区域,它一般是显示驱动的内部缓冲区在内存中的映射。android

一旦用户进程把图像数据复制到Framebuffer中,显示驱动会一个像素一个像素地扫描整个Framebuffer,并根据其中的值更新屏幕上像素点的颜色。api

驱动中这个更新屏幕的动做是固定的,它的周期就是咱们常说的刷新率数组

Android关于图像渲染显示的架构图以下:
image缓存

结合这张图,咱们须要重点关注的是:markdown

  • Native Framework中的Surfacesession

    • 不管开发者使用什么渲染API,一切内容都会渲染到Surface
    • Surface中会关联一个BufferQueue用于提供图像数据缓存
    • 大多数客户端使用OpenGL ESVulkan渲染到Surface
    • 有些客户端使用Canvas渲染到Surface
  • Image Stream Producer的定义是可以生成图形缓冲区以供消耗的任何对象。每一个Producer都会关联一个Surface,例如数据结构

    • Canvas 2DJava层主要是经过View中建立的Surface对象来进行操做
      • Surface对象会与SurfaceFlinger进行关联,并经过lockCanavas()接口获取Canvas对象
      • lockCanvas()会将CPU渲染程序链接到BufferQueue的生产方,直到Surface被销毁时才会断开链接
    • mediaserver视频解码器:经过MediaPlayersetSurfaceHolder()接口与SurfaceView中的Surface进行绑定
  • 对于Image Stream Consumer来讲,主要是SurfaceFlinger,该系统服务会消耗当前可见的Surface,并使用WindowManager中提供的信息将它们合成到显示部分。架构

    • SurfaceFlinger是能够修改所显示部份内容的惟一服务。SurfaceFlinger使用OpenGLHardware Composer 来合成一组Surface
    • 当应用进入前台时,它会从WindowManager请求缓冲区。而后,WindowManager会从SurfaceFlinger请求layer
      • layersurface(包含BufferQueue)和SurfaceControl(包含屏幕框架等层元数据)的组合。
    • SurfaceFlinger建立layer并将其发送至WindowManager
    • 而后,WindowManagerSurface发送至应用,但会保留SurfaceControl来操控应用在屏幕上的外观。
  • Window Positioning中的WindowManager主要是用来控制Window对象app

    • Window对象是用来存放View对象的容器,每一个Window对象都会关联Surface对象
    • WindowManager监视Window对象的生命周期、输入和焦点事件、屏幕方向、转换、动画、位置、变换、z顺序等
    • 而后将全部Window元数据发送给SurfaceFlingerSurfaceFlinger利用这些元数据把本身管理的全部Surface组合成layer
    • 而后交给Hardware Composer作进一步处理
  • HAL层中的Hardware Composer(HWC)会根据当前硬件来进一步进行缓冲区的组合,它的具体实现依赖于特定的显示设备

    • 官网关于HWC的数据流以下:

    image

    • SurfaceFlinger做为clientHWC提供一个完整的layer列表,而后询问HWC计划如何处理
    • HWC会将这些layer标记为client合成或者device合成并告知SurfaceFlinger
    • SurfaceFlinger将处理标记为client合成layer,而后经过BufferQueue传递给HWC
    • 余下的layerHWC自行处理

网上一篇颇有趣的渲染总结(文中有些错误,但瑕不掩瑜):Android渲染原理

VSYNC信号

前面提到Linux使用Framebuffer来用做显示输出。可是,若是在屏幕更新到一半时,用户进程更新了Framebuffer中的数据,将致使屏幕上画面的上半部分是前一帧的画面,下半部分变成了新的画面。固然这种异常会在下次刷新时纠正过来,可是在用户感知上画面会出现闪烁感

  • 针对这种状况,早期的解决方法是使用双缓冲机制,双缓冲就是提供两块Framebuffer,一块用于显示,另外一块用于数据更新,数据准备好后,经过ioctl操做告诉显示设备切换用于显示的Framebuffer,这样图像就能快速的显示出来了
  • 可是双缓冲并无彻底解决问题,虽然双缓冲切换的速度很快,可是若是切换的时间点不对,在画面更新一半的时候进行切换,仍是会出现单缓冲区遇到的闪烁问题
  • 固然,能够在底层进行控制,当收到切换请求后内部并不立刻执行,而是等到刷新完成后再切换,这样能够彻底避免画面重叠的问题
  • 可是,这样作会带来新的问题,若是ioctl操做完成后缓冲区没有切换,应用就不能肯定什么时候能够再使用缓存区,只能经过ioctl不停地查询缓冲区状态,直到切换完成。这种CPU主动查询的方式很低效

为此Android让底层固定地发送信号给用户进程,通知进程切换的时机,这样就避免了用户进程主动查询的操做。而这个信号就是VSYNC信号

官方传送门:VSYNC

官方描述以下:VSYNC信号用来同步整个显示流程(Display Pipeline)显示流程包括app渲染、SurfaceFlinger合成、HWC(硬件渲染)组成

(这部分感受原文更容易理解)VSYNC synchronizes the time apps wake up to start rendering, the time SurfaceFlinger wakes up to composite the screen, and the display refresh cycle.

VSYNC信号应该由显示驱动产生,这样才能达到最佳效果。可是Android为了能运行在不支持VSYNC机制的设备上,也提供了用软件来模拟产生VSYNC信号的手段

官网描述:经过HWC来产生VSYNC信号,并经过接口回调将事件进行发送(主要是SurfaceFlinger进行事件接收)

基础知识铺垫完成,咱们先来看看Surface

Surface

官网对Surface的描述是:A surface is an interface for a producer to exchange buffers with a consumer.

上面描述的是一种生产者-消费者的模式,而Surface充当了中间衔接的角色。

ActivityUI显示为例:

  • 生产者的任务就是把图形绘制在Surface对象上

    • 比较出名的生产者就是SurfaceView组件了
  • SurfaceFlinger做为消费者会把全部Surface对应的图像层混合在一块儿

  • 最后消费者将其输出到FrameBuffer中,这样在屏幕上就看到最后合成的图像了

下面咱们从Java层开始分析Surface

应用中Surface的建立过程

应用开发中不多直接使用Surface,由于每一个Activity中都已经建立好了各自的Surface对象,一般只有一些特殊的应用才须要在Activity以外再去建立Surface,例如相机、视频播放应用。

不过,一般这些应用也是经过建立SurfaceView来使用Surface

须要注意的是,在应用中不能直接去建立一个可用的Surface对象(也能够说直接建立出的对象没什么实际用途),由于这样建立出的Surface对象和SurfaceFlinger之间没有任何关联。

该如何创见一个可用的Surface对象呢?
咱们看下Surface类的定义:

public class Surface implements Parcelable {
    long mNativeObject;
    // 一个无参构造,空实现
    public Surface() {
    }
    public Surface(SurfaceTexture surfaceTexture) {
        if (surfaceTexture == null) {
            throw new IllegalArgumentException("surfaceTexture must not be null");
        }
        mIsSingleBuffered = surfaceTexture.isSingleBuffered();
        synchronized (mLock) {
            mName = surfaceTexture.toString();
            setNativeObjectLocked(nativeCreateFromSurfaceTexture(surfaceTexture));
        }
    }
}
复制代码

Surface类对外有两个构造方法:

  • 一个是无参构造,实现也是空的

    • 注释中说这个主要是给readFromParcel()反序列化用的
    • 那咱们看下readFromParcel()方法
    public void readFromParcel(Parcel source) {
        if (source == null) {
            throw new IllegalArgumentException("source must not be null");
        }
        synchronized (mLock) {
            mName = source.readString();
            mIsSingleBuffered = source.readInt() != 0;
            setNativeObjectLocked(nativeReadFromParcel(mNativeObject, source));
        }
    }
    复制代码
  • 另外一个须要传递SurfaceTexture对象做为参数

    • 这就复杂了,还要准备一个SurfaceTexture对象

聪明的咱们会发现,readFromParcel()new Surface(SurfaceTexture surfaceTexture)都会执行一个setNativeObjectLocked()方法,咱们看下方法实现:

private void setNativeObjectLocked(long ptr) {
        if (mNativeObject != ptr) {
            ...
            mNativeObject = ptr;
            ...
        }
    }
复制代码

setNativeObjectLocked()方法很简单,只是更新了mNativeObject变量的数值,重点就是参数了:

  • setNativeObjectLocked(nativeReadFromParcel(mNativeObject, source));
  • setNativeObjectLocked(nativeCreateFromSurfaceTexture(surfaceTexture));

这两个setNativeObjectLocked()方法的调用从参数的命名来看是针对不一样数据来源的处理。

看来要看下native的实现了,以nativeReadFromParcel()为例来看下:

static jlong nativeReadFromParcel(JNIEnv* env, jclass clazz, jlong nativeObject, jobject parcelObj) {
    Parcel* parcel = parcelForJavaObject(env, parcelObj);
    ...
    android::view::Surface surfaceShim;
    // 解析 Parcel 数据,并填充到 native层 的 Surface对象 surfaceShim
    surfaceShim.readFromParcel(parcel, /*nameAlreadyRead*/true);
    // 将传入的指针转换为 native层 的 Surface对象 self
    sp<Surface> self(reinterpret_cast<Surface *>(nativeObject));
    // 比对 surfaceShim 和 self 中的 Binder 对象 IGraphicBufferProducer
    if (self != nullptr
            && (IInterface::asBinder(self->getIGraphicBufferProducer()) ==
                    IInterface::asBinder(surfaceShim.graphicBufferProducer))) {
        // 判断是同一个 IGraphicBufferProducer ,直接返回当前指针
        return jlong(self.get());
    }
    sp<Surface> sur;
    if (surfaceShim.graphicBufferProducer != nullptr) {
        // IGraphicBufferProducer 不一样
        // 且 surfaceShim 的 IGraphicBufferProducer 不为空
        // 建立一个新的 Surface 对象 sur
        sur = new Surface(surfaceShim.graphicBufferProducer, true);
        sur->incStrong(&sRefBaseOwner);
    }
    ...
    // 将 sur 的指针返回给 Java 层
    return jlong(sur.get());
}
复制代码

到这里咱们不难看出

  • Java层Surface对象最重要的数据是mNativeObject变量
    • mNativeObject是一个指针,指向的native层的Surface对象
  • native层在判断是否新建Surface对象的逻辑依赖的是IGraphicBufferProducer对象
    • IGraphicBufferProducer对象是一个Binder引用对象

那么接下来咱们重点就是这个IGraphicBufferProducer了。

咱们先看下native层Surface类的继承关系:

class Surface : public ANativeObjectBase<ANativeWindow, Surface, RefBase>
复制代码

ANativeObjectBase的定义以下:

template <typename NATIVE_TYPE, typename TYPE, typename REF,
        typename NATIVE_BASE = android_native_base_t>
class ANativeObjectBase : public NATIVE_TYPE, public REF
{...}
复制代码

整理成继承关系图就是:
image

再看下Surface的构造方法:

Surface::Surface(const sp<IGraphicBufferProducer>& bufferProducer, bool controlledByApp)
      : mGraphicBufferProducer(bufferProducer),
        mCrop(Rect::EMPTY_RECT),
        mBufferAge(0),
        ...
        mFrameEventHistory(std::make_unique<ProducerFrameEventHistory>()) {
        ... // 初始化各类成员变量
}
复制代码

从构造函数的参数能够看到,native层SurfaceIGraphicBufferProducer对象保存到了mGraphicBufferProducer变量中。

暂时仍是不清楚mGraphicBufferProducer哪里来的,咱们去WMS中看看

WMSSurface的建立过程

此处要从ActivityonResume()生命周期提及

onResume()WMS.relayoutWindow()

咱们已经知道,当AMS触发onResume()生命周期时会调用到ActivityThread类的handleResumeActivity()方法,代码以下:

public void handleResumeActivity(...) {
        ...
        // 此处会触发 onResume 声明周期回调
        final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
        ...
        ViewManager wm = a.getWindowManager();
        ...// 省略不少 Window 处理逻辑
        wm.addView(decor, l);
        ...
    }
复制代码

从方法中能够看到,执行完onResume()后调用了ViewManageraddView(decor, l)方法

知识点:onResume方法调用后才真正进行View的添加

ViewManager是一个接口类,真正的实现类是WindowManagerImpladdView()方法实现也很简单:

public void addView(...) {
        applyDefaultToken(params);
        mGlobal.addView(...);
    }
复制代码

调用了mGlobaladdView()方法方法,mGlobal的类型是WindowManagerGlobal,代码以下:

public void addView(...) {
        ...
        ViewRootImpl root;
        synchronized (mLock) {
            ...
            root = new ViewRootImpl(view.getContext(), display);
            view.setLayoutParams(wparams);
            mViews.add(view);
            mRoots.add(root);
            mParams.add(wparams);
            try {
                root.setView(view, wparams, panelParentView);
            }
            ...
        }
    }
复制代码

WindowManagerGlobal类的addView()先是建立了一个新的ViewRootImpl对象,而后调用了ViewRootImpl对象的setView()方法。

ViewRootImpl类中setView()调用流程以下:

class ViewRootImpl{
    /** * 这里也是直接 new 出来的对象 Surface * 前面已经介绍过,这个对象须要和 native层进行绑定后才能正常使用 */
    public final Surface mSurface = new Surface();
    ViewRootImpl(Context context, Display display){
        ...
        // 此方法会建立 Session 对象
        mWindowSession = WindowManagerGlobal.getWindowSession();
        ...
    }
    public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
        synchronized (this) {
            if (mView == null) {
                mView = view;
                ...
                // 内部方法调用
                requestLayout();
                ...
                // 此方法会建立 SurfaceSession
                res = mWindowSession.addToDisplay(...);
                ...
            }
        }
    }
    public void requestLayout() {
        if (!mHandlingLayoutInLayoutRequest) {
            ...
            scheduleTraversals();
        }
    }
    void scheduleTraversals() {
        if (!mTraversalScheduled) {
            ...
            // 异步执行 mTraversalRunnable
            mChoreographer.postCallback(
                    Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
            ...
        }
    }
    final class TraversalRunnable implements Runnable {
        @Override
        public void run() {
            doTraversal();
        }
    }
    void doTraversal() {
        if (mTraversalScheduled) {
            ...
            performTraversals();
            ...
        }
    }
    private void performTraversals() {
        ...
        relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
        ...
    }
    private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility, boolean insetsPending) throws RemoteException {
        ...
        // 调用 mWindowSession 的 relayout 方法,并将 mSurface 对象传递过去
        int relayoutResult = mWindowSession.relayout(..., mSurface);
        ...
        return relayoutResult;
    }
}
复制代码

setView()方法最后调用的是mWindowSessionrelayout()方法。

mWindowSession类型是IWindowSession,是一个Binder引用对象。真正的Binder服务实现是com.android.server.wm.Session类:

class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
    public Session(WindowManagerService service, ...) {
        mService = service;
        ...
    }
    public int relayout(..., Surface outSurface) {
        ...
        int res = mService.relayoutWindow(..., outSurface);
        ...
        return res;
    }
}
复制代码

终于走到了WMS中,调用的是WMSrelayoutWindow()方法

WMS.relayoutWindow()SurfaceControl.nativeCreate()

Surface相关的调用关系以下:

class WindowManagerService{
    public int relayoutWindow(..., Surface outSurface) {
        ...
        result = createSurfaceControl(outSurface, ...);
        ...
        return result;
    }
    private int createSurfaceControl(Surface outSurface, ...) {
        ...
        WindowSurfaceController surfaceController;
        ...
        surfaceController = winAnimator.createSurfaceLocked(win.mAttrs.type, win.mOwnerUid);
        ...
        if (surfaceController != null) {
            surfaceController.getSurface(outSurface);
        } else {
            ...
            outSurface.release();
        }
        return result;
    }
}
class WindowSurfaceController{
    public WindowSurfaceController(...) {
        ...
        final SurfaceControl.Builder b = win.makeSurface()
                ...
                .setMetadata(windowType, ownerUid);
        mSurfaceControl = b.build();
    }
    void getSurface(Surface outSurface) {
        outSurface.copyFrom(mSurfaceControl);
    }
}
class Surface{
    public void copyFrom(SurfaceControl other) {
        if (other == null) {
            throw new IllegalArgumentException("other must not be null");
        }
        long surfaceControlPtr = other.mNativeObject;
        if (surfaceControlPtr == 0) {
            throw new NullPointerException(
                    "null SurfaceControl native object. Are you using a released SurfaceControl?");
        }
        long newNativeObject = nativeGetFromSurfaceControl(surfaceControlPtr);
        synchronized (mLock) {
            if (mNativeObject != 0) {
                nativeRelease(mNativeObject);
            }
            setNativeObjectLocked(newNativeObject);
        }
    }
}
复制代码

在上面的relayoutWindow()方法中

  • WMS先经过winAnimatorcreateSurfaceLocked()方法获得了一个WindowSurfaceController对象
    • WindowSurfaceController对象封装了SurfaceControl对象
  • 而后WMS调用WindowSurfaceController对象的getSurface()方法来对Surface对象进行填充
    • getSurface()对象只是利用自身保存的mSurfaceControl对象
    • 经过SurfacecopyFrom()方法对Surface对象进行填充处理
  • copyFrom()方法
    • 调用nativeGetFromSurfaceControl()方法获得一个native层的Surface对象指针
    • 而后经过setNativeObjectLocked()方法将指针保存到成员变量mNativeObject

关键点又回到了native层的nativeGetFromSurfaceControl()方法,它的代码以下:

static jlong nativeGetFromSurfaceControl(JNIEnv* env, jclass clazz, jlong surfaceControlNativeObj) {
    sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(surfaceControlNativeObj));
    sp<Surface> surface(ctrl->getSurface());
    if (surface != NULL) {
        surface->incStrong(&sRefBaseOwner);
    }
    return reinterpret_cast<jlong>(surface.get());
}
复制代码

nativeGetFromSurfaceControl()方法是经过native层的SurfaceControlgetSurface()方法来获取Surface对象。咱们再看下getSurface()方法:

sp<Surface> SurfaceControl::getSurface() const {
    Mutex::Autolock _l(mLock);
    if (mSurfaceData == 0) {
        return generateSurfaceLocked();
    }
    return mSurfaceData;
}
sp<Surface> SurfaceControl::generateSurfaceLocked() const {
    mSurfaceData = new Surface(mGraphicBufferProducer, false);
    return mSurfaceData;
}
复制代码

SurfaceControlgetSurface()方法中

  • mSurfaceData指针为空时才会经过generateSurfaceLocked()方法建立一个新的Surface对象
    • Surface对象中很关键的IGraphicBufferProducer在这里传入的是SurfaceControl的成员变量mGraphicBufferProducer
  • 不然直接返回mSurfaceData指针

getSurface()方法的逻辑中咱们不难看出,SurfaceControl对象和Surface对象是关联在一块儿的,一对一的关系

更关键的是构造Surface对象的核心参数居然是SurfaceControl中的成员变量。。。。。。。。

没办法,要先搞定SurfaceControl的建立过程才能够

前面已经讲过,WMS经过winAnimator.createSurfaceLocked()方法建立了WindowSurfaceController对象,WindowSurfaceController对象初始化时就会建立SurfaceControl,咱们看下建立过程:

class WindowStateAnimator{
    WindowSurfaceController createSurfaceLocked(int windowType, int ownerUid) {
        ...
        // mSession 的类型就是前面提到的 Session 类,IWindowSession Binder服务类
        mSurfaceController = new WindowSurfaceController(mSession.mSurfaceSession, ...);
        ...
        return mSurfaceController;
    }
}
class WindowSurfaceController{
    public WindowSurfaceController(SurfaceSession s, ...) {
        ...
        final SurfaceControl.Builder b = win.makeSurface()
                ...
                .setMetadata(windowType, ownerUid);
        // 经过 Builder 模式建立的
        mSurfaceControl = b.build();
    }
}
class SurfaceControl{
    public static class Builder {
        ...
        public SurfaceControl build() {
            ...
            // 调用私有构造方法
            return new SurfaceControl(mSession, ...);
        }
        ...
    }
    private SurfaceControl(SurfaceSession session, ...) throws OutOfResourcesException, IllegalArgumentException {
        ...
        mNativeObject = nativeCreate(session, ...);
        if (mNativeObject == 0) {
            throw new OutOfResourcesException(
                    "Couldn't allocate SurfaceControl native object");
        }
        ...
    }
}
复制代码

能够看到

  • 建立SurfaceControl对象的全程都携带着一个SurfaceSession对象。
  • 同时这个SurfaceSession对象在SurfaceControl的构造方法中经过nativeCreate()传递到了native层,用来建立native层的对象
  • Java层Surface对象同样,SurfaceControl对象也会将native层对象的指针保存到mNativeObject

关键仍是在nativeCreate()方法,咱们继续。。

nativeCreate()方法以下:

static jlong nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj, ...) {
    ScopedUtfChars name(env, nameStr);
    sp<SurfaceComposerClient> client(android_view_SurfaceSession_getClient(env, sessionObj));
    ...
    sp<SurfaceControl> surface;
    status_t err = client->createSurfaceChecked(
            String8(name.c_str()), w, h, format, &surface, flags, parent, windowType, ownerUid);
    ...
    return reinterpret_cast<jlong>(surface.get());
}
复制代码

nativeCreate()方法中又出现了一个新的类型SurfaceComposerClient,并且native层SurfaceControl对象就是经过它的createSurfaceChecked()来建立的

耐心、耐心、耐心。。。。 崩溃的时候多说几回

上面方法中的SurfaceComposerClient对象是经过android_view_SurfaceSession_getClient()方法获得的,看JNI的命名格式能够推算它和SurfaceSession类也有关系,内容以下:

sp<SurfaceComposerClient> android_view_SurfaceSession_getClient( JNIEnv* env, jobject surfaceSessionObj) {
    return reinterpret_cast<SurfaceComposerClient*>(
            env->GetLongField(surfaceSessionObj, gSurfaceSessionClassInfo.mNativeClient));
}
复制代码

android_view_SurfaceSession_getClient()方法中的参数surfaceSessionObj是在Java层调用nativeCreate()方法时传递的参数,类型是SurfaceSession

这里其实是将SurfaceSession对象中成员变量mNativeClient的值取出来后,转换为SurfaceComposerClient对象返回

这说明SurfaceComposerClient对象和SurfaceSession对象也是一块儿建立出来的,咱们继续看下SurfaceSessionSurfaceComposerClient的建立过程

SurfaceControl.nativeCreateComposerService

须要知道的一个重要前提:每一个用户进程在WMS中都有且只有一个对应的Session对象,前面已经介绍Session是一个实现了IWindowSession接口的Binder服务类

Session的成员变量mSurfaceSession是在Session对象初始化时建立的,那么Session对象在何时建立的呢?
跟踪代码发现流程以下:

  • ViewRootImpl初始化时会调用WindowManagerGlobal.getWindowSession()方法
  • WindowManagerGlobal.getWindowSession()会调用WMSopenSession()方法
  • openSession()方法中便会在WMS中建立一个新的Session对象

对于SurfaceSession的初始化,是在Session对象的windowAddedLocked()方法中,那么windowAddedLocked()方法又是在哪里调用的呢?
一样,咱们跟踪下方法调用:

  • ViewRootImplsetView()方法中会调用mWindowSession.addToDisplay(...)方法
  • mWindowSession.addToDisplay(...)方法会调用WMSaddWindow()方法
  • WMSaddWindow()方法会调用WindowStateattach()方法
  • attach()方法会调用SessionwindowAddedLocked()方法

这样就串起来了,如今咱们能够继续学习SurfaceSession的构造方法了:

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

很简洁,源码注释也很关键。咱们看下SurfaceSessionnativeCreate()方法:

static jlong nativeCreate(JNIEnv* env, jclass clazz) {
    SurfaceComposerClient* client = new SurfaceComposerClient();
    // 请注意此方法的调用
    // 该方法会触发 onFirstRef() 的执行
    client->incStrong((void*)nativeCreate);
    return reinterpret_cast<jlong>(client);
}
复制代码

nativeCreate()直接建立了一个SurfaceComposerClient对象,也没有参数。不过SurfaceComposerClient类是从RefBase类派生出来的,咱们看下它的构造函数和onFirstRef函数:

SurfaceComposerClient::SurfaceComposerClient()
    : mStatus(NO_INIT)
{
}
// onFirstRef() 是 RefBase 提供的回调接口
// 当首次调用 incStrong() 方法时便会执行此方法
void SurfaceComposerClient::onFirstRef() {
    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
    if (sf != 0 && mStatus == NO_INIT) {
        // 此处 rootProducer 应该为 null
        auto rootProducer = mParent.promote();
        sp<ISurfaceComposerClient> conn;
        // 因此在此处执行的是 sf->createConnection() 方法
        conn = (rootProducer != nullptr) ? sf->createScopedConnection(rootProducer) :
                sf->createConnection();
        if (conn != 0) {
            mClient = conn;
            mStatus = NO_ERROR;
        }
    }
}
复制代码

构造方法很简单,只是将mStatus设置为NO_INIT

重点是在onFirstRef()方法中

  • 先调用了ComposerServicegetComposerService()方法来获得一个ISurfaceComposer的指针
  • 而后调用它的createConnection()方法建立一个ISurfaceComposerClient对象
  • 而后将mClient指向这个ISurfaceComposerClient对象

咳咳咳,按照上面的调用流程咱们尚未找到关于IGraphicBufferProducer的信息,如今又多出来了一个ISurfaceComposerClient。。。

好吧好吧,梳理下这部分关系先

WMSSurface关系总结

上面介绍的WMS中涉及和Surface有关的类关系以下: image

看上去就挺复杂的:

  • SurfaceControlSurface是成对建立的,考虑到绘制等需求,它们的数量会比较多
  • SessionSurfaceSessionSurfaceComposerClient对象是和链接WMS的用户进程的数量相同
  • SurfaceComposerClient的做用是建立Surface
  • SurfaceControl经过SurfaceComposerClient来获取Surface
  • SurfaceComposerClientComposerService的具体实现类

ComposerService再到SurfaceFlinger

ComposerService是一个单例模式的普通类,定义以下:

class ComposerService : public Singleton<ComposerService>
{
    sp<ISurfaceComposer> mComposerService;
    sp<IBinder::DeathRecipient> mDeathObserver;
    Mutex mLock;

    ComposerService();
    void connectLocked();
    void composerServiceDied();
    friend class Singleton<ComposerService>;
public:
    static sp<ISurfaceComposer> getComposerService();
};
复制代码

前面的onFirstRef()方法中调用了ComposerService类的静态方法getComposerService(),咱们看下它的实现:

/*static*/ sp<ISurfaceComposer> ComposerService::getComposerService() {
    ComposerService& instance = ComposerService::getInstance();
    Mutex::Autolock _l(instance.mLock);
    if (instance.mComposerService == NULL) {
        ComposerService::getInstance().connectLocked();
        ...
    }
    return instance.mComposerService;
}
复制代码

getComposerService()经过调用父类SingletongetInstance()方法来取得实例对象,而后调用ComposerServiceconnectLocked()方法:

void ComposerService::connectLocked() {
    const String16 name("SurfaceFlinger");
    while (getService(name, &mComposerService) != NO_ERROR) {
        usleep(250000);
    }
    ...
}
复制代码

connectLocked()方法中链接了SurfaceFlinger服务对象,而后把对象指针保存到mComposerService中。

ComposerService其实只是SurfaceFlinger的代理,它把SurfaceFlinger服务接口包装了起来

getComposerService()返回的就是mComposerService对象指针,也就是SurfaceFlingerBinder对象。

前面提到,SurfaceComposerClient对象的onFirstRef()方法中

  • 在经过ComposerService::getComposerService()得到了mComposerService指针后
  • 调用了mComposerService对象的createConnection()方法。
  • 按照刚才的逻辑,其实调用是SurfaceFlinger服务的相关函数接口。

SurfaceFlinger中接口实现以下:

sp<ISurfaceComposerClient> SurfaceFlinger::createConnection() {
    return initClient(new Client(this));
}
static sp<ISurfaceComposerClient> initClient(const sp<Client>& client) {
    status_t err = client->initCheck();
    if (err == NO_ERROR) {
        return client;
    }
    return nullptr;
}
复制代码

createConnection()函数中建立了一个Client类型对象,而后将其返回给调用者,关于Client类的定义以下:

class Client : public BnSurfaceComposerClient
复制代码

Client是一个Binder服务类,虽然叫Client。而mComposerService保存的也就是这个服务对象的指针

咱们再回到SurfaceControl的建立过程

  • nativeCreate()方法中调用了SurfaceComposerClientcreateSurfaceChecked()方法
status_t SurfaceComposerClient::createSurfaceChecked(...) {
    sp<SurfaceControl> sur;
    status_t err = mStatus;
    if (mStatus == NO_ERROR) {
        sp<IBinder> handle;
        sp<IBinder> parentHandle;
        sp<IGraphicBufferProducer> gbp;

        if (parent != nullptr) {
            parentHandle = parent->getHandle();
        }
        err = mClient->createSurface(name, w, h, format, flags, parentHandle,
                windowType, ownerUid, &handle, &gbp);
        ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err));
        if (err == NO_ERROR) {
            *outSurface = new SurfaceControl(this, handle, gbp, true /* owned */);
        }
    }
    return err;
}
复制代码

createSurfaceChecked()方法

  • 先是调用了SurfaceFlinger::Client对象的createSurface()方法去进行建立操做
    • 请留意传递的参数,handlegbpparentHandle都是Binder对象
      • sp<IGraphicBufferProducer> gbp就是咱们找寻已久的参数。。。。
      • 这些参数都会在SurfaceFlinger中进行设置
  • 最后确认SurfaceFlinger::Client对象的createSurface()执行完成没有错误,建立SurfaceControl对象

SurfaceFlinger中建立Surface

SurfaceFlinger::Client对象的createSurface()方法以下:

status_t Client::createSurface(..., sp<IGraphicBufferProducer>* gbp) {
    ...
    return mFlinger->createLayer(..., gbp, &parent);
}
复制代码

调用的是SurfaceFlingercreateLayer()方法,代码以下:

status_t SurfaceFlinger::createLayer(..., sp<IGraphicBufferProducer>* gbp, sp<Layer>* parent) {
    ...
    status_t result = NO_ERROR;
    sp<Layer> layer;
    String8 uniqueName = getUniqueLayerName(name);
    // 这里分红了两种建立模式:Normal 和 Color
    switch (flags & ISurfaceComposerClient::eFXSurfaceMask) {
        case ISurfaceComposerClient::eFXSurfaceNormal: // normal
            result = createBufferLayer(client,
                    uniqueName, w, h, flags, format,
                    handle, gbp, &layer);
            break;
        case ISurfaceComposerClient::eFXSurfaceColor: // color
            result = createColorLayer(client,
                    uniqueName, w, h, flags,
                    handle, &layer);
            break;
        default:
            result = BAD_VALUE;
            break;
    }
    ...
    return result;
}
复制代码

createLayer()方法按照两种模式进行建立

  • 一种是eFXSurfaceNormal模式,经过createBufferLayer()方法建立,方法以下:

    status_t SurfaceFlinger::createBufferLayer(..., sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer) {
        // initialize the surfaces
        switch (format) {
        case PIXEL_FORMAT_TRANSPARENT:
        case PIXEL_FORMAT_TRANSLUCENT:
            // 透明或半透明设置格式为 RGBA
            format = PIXEL_FORMAT_RGBA_8888;
            break;
        case PIXEL_FORMAT_OPAQUE:
            // 不透明设置格式为 RGBX
            format = PIXEL_FORMAT_RGBX_8888;
            break;
        }
        sp<BufferLayer> layer = new BufferLayer(this, client, name, w, h, flags);
        status_t err = layer->setBuffers(w, h, format, flags);
        if (err == NO_ERROR) {
            *handle = layer->getHandle();
            // 咱们关注的 IGraphicBufferProducer 在这里赋值了
            *gbp = layer->getProducer();
            *outLayer = layer;
        }
        return err;
    }
    复制代码
    • 方法中先是肯定相应的像素格式,而后建立新的BufferLayer对象,调用对象的setBuffers()设置宽高和像素格式
    • Surface中重要的gdp等参数也会在这里进行设置
  • 一种是eFXSurfaceColor模式,经过createColorLayer()方法建立:看参数传入和gdp没啥关系,不用太过关注

    status_t SurfaceFlinger::createColorLayer(...,
            sp<IBinder>* handle, sp<Layer>* outLayer)
    {
        *outLayer = new ColorLayer(this, client, name, w, h, flags);
        *handle = (*outLayer)->getHandle();
        return NO_ERROR;
    }
    复制代码
    • 方法比较简单只是建立了一个ColorLayer对象,也没有setBuffers()等操做

咱们重点关注eFXSurfaceNormal模式的建立逻辑

终于,咱们找到了sp<IGraphicBufferProducer>* gbp的来源,是经过layer->getProducer()方法

layer->getProducer()方法以下:

sp<IGraphicBufferProducer> BufferLayer::getProducer() const {
    return mProducer;
}
复制代码

layer->getProducer()方法比较简单,只是返回了一个mProducer对象的指针

mProducer对象的建立是在BufferLayer::onFirstRef()方法中

void BufferLayer::onFirstRef() {
    Layer::onFirstRef();
    // Creates a custom BufferQueue for SurfaceFlingerConsumer to use
    sp<IGraphicBufferProducer> producer;
    sp<IGraphicBufferConsumer> consumer;
    // 经过 BufferQueue 的 createBufferQueue 方法建立 producer 和 consumer
    BufferQueue::createBufferQueue(&producer, &consumer, true);
    // 建立 mProducer
    mProducer = new MonitoredProducer(producer, mFlinger, this);
    ...
}
复制代码

onFirstRef()方法中

  • 经过BufferQueue::createBufferQueue()方法建立producerconsumer
    void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer, sp<IGraphicBufferConsumer>* outConsumer, bool consumerIsSurfaceFlinger) {
        sp<BufferQueueCore> core(new BufferQueueCore());
        sp<IGraphicBufferProducer> producer(new BufferQueueProducer(core, consumerIsSurfaceFlinger));
        sp<IGraphicBufferConsumer> consumer(new BufferQueueConsumer(core));
    
        *outProducer = producer;
        *outConsumer = consumer;
    }
    复制代码
  • 利用建立好的producer对象建立MonitoredProducer对象

MonitoredProducer头文件定义以下:

class MonitoredProducer : public BnGraphicBufferProducer {
public:
    MonitoredProducer(const sp<IGraphicBufferProducer>& producer,
            const sp<SurfaceFlinger>& flinger,
            const wp<Layer>& layer);
    virtual ~MonitoredProducer();
    ...
private:
    // 在 BufferLayer 的 onFirstRef() 中经过 BufferQueue::createBufferQueue() 建立
    sp<IGraphicBufferProducer> mProducer;
    sp<SurfaceFlinger> mFlinger;
    wp<Layer> mLayer;
}
复制代码

虽然MonitoredProducer是一个Binder实体对象,但从业务上来说它仅仅是个代理

真正管理图像缓冲区的是经过BufferQueue::createBufferQueue()方法建立的BufferQueueProducer producer对象

终于接近IGraphicBufferProducer的本质了,到这里咱们其实能够结束WMSSurface的建立流程了。先回顾下整个建立流程:
image 上图分了三部分

  • 绿色部分:SurfaceSession的初始化
  • 蓝色部分:ViewRootImplsetView()中执行performTraversals()
    • 这部分主要是建立SurfaceControl对象
    • 而后对Surface对象进行填充
    • scheduleTraversals()调用流程来看,这是一个异步过程
  • 青色部分:ViewRootImplsetView()中执行session.addToDisplay()
    • 这部分主要是建立SurfaceSession对象
    • native层建立SurfaceComposerClient对象

须要注意的一点是SurfaceControl对象的建立须要SurfaceSession对象做为参数。但setView()方法中SurfaceSession对象的建立放在了SurfaceControl对象的后面
一开始其实挺疑惑的,核心仍是在scheduleTraversals()的异步调用过程,感兴趣的同窗能够参考:scheduleTraversals到底作了什么

管理图像缓冲区IGraphicBufferProducer

咱们一直强调Surface中最重要的对象是IGraphicBufferProducer,最后咱们也找到了它对应的Binder实体对象MonitoredProducer对象

  • 对于MonitoredProducer对象来讲,它又关联了一个sp<IGraphicBufferProducer>对象mProducer
    • mProducer对象具体的实现类是BufferQueueProducer

前面说Surface像一张画布,那么Surface为何要和BufferQueue关联呢?

  • 对于图像显示设备而言,它的刷新周期是固定的,必须在它须要图像的时候把数据准备好
  • 播放动画时,每秒要播放至少24帧画面才能造成比较真实的动画效果
    • 而这些图像数据都是CPU解码获得的,准备它们须要时间
  • 播放视频时的每一帧也须要在指定时间播放
  • 所以解码器会提早准备好一批数据,这些数据保存在解码器内部的缓冲区中
  • 当时间到达时,解码器会把内部缓冲区的图像数据复制到Surface
  • 可是显示设备并不能马上把数据取走,所以Surface须要缓冲区来临时保存数据

BufferQueue操做官方图解以下:
image

从前面的BufferQueue::createBufferQueue()中能够看出:

  • MonitoredProducer对象也只是一个代理,真正的业务处理对象是在createBufferQueue()方法中建立的BufferQueueProducer对象
  • 除此以外方法中还涉及了BufferQueueCoreBufferQueueConsumer对象的建立

BufferQueue-Core|Producer|Consumer

前面已经介绍,在BufferLayeronFirstRef()方法中经过BufferQueue::createBufferQueue()方法建立了三个对象:BufferQueueCoreBufferQueueConsumerBufferQueueProducer

其中BufferQueueCore是核心,把BufferQueueConsumerBufferQueueProducer对象链接在了一块儿

关于BufferQueue的工做方式,官网有个比较直观的叙述,翻译以下:

  • Consumer建立并拥有BufferQueue数据结构,而且可存在于与其Producer不一样的进程中
  • Producer须要缓冲区时,它会经过调用dequeueBuffer()BufferQueue请求一个可用的缓冲区,并指定缓冲区的宽度、高度、像素格式和用法标志。
  • 而后,Producer填充缓冲区并经过调用queueBuffer()将缓冲区返回到队列
  • 接下来,Consumer经过acquireBuffer()获取该缓冲区并使用该缓冲区的内容
  • Consumer操做完成后,它会经过调用releaseBuffer()将该缓冲区返回到队列

流程较为清晰,咱们从源码层面再看下,首先是BufferQueueCore中的关键定义:

class BufferQueueCore : public virtual RefBase {
    friend class BufferQueueProducer;
    friend class BufferQueueConsumer;
    ...
private:
    BufferQueueDefs::SlotsType mSlots;
}
复制代码

C++中的friend在这里用来使ProducerConsumer能够访问Core中的成员变量。mSlots是一个64长度的BufferSlot数组,稍后细讲

再看下BufferQueueProducer类的定义:

class BufferQueueProducer : public BnGraphicBufferProducer,
                            private IBinder::DeathRecipient {
...
private:
    sp<BufferQueueCore> mCore;                                
}
复制代码

再看看BufferQueueConsumer类的定义:

class BufferQueueConsumer : public BnGraphicBufferConsumer {
...
private:
    sp<BufferQueueCore> mCore;
}
复制代码

不难看出,Producer对象和Consumer对象经过mCore对象链接在一块儿,查看ProducerConsumer这两个对象的具体方法咱们就会发现,不少操做都是直接经过mCore对象的函数来实现的。

ConsumerProducer的接口定义

继续看下BufferQueueConsumerBufferQueueProducer的基类,分别是BnGraphicBufferProducerBnGraphicBufferConsumer,定义以下:

class BnGraphicBufferProducer : public BnInterface<IGraphicBufferProducer>
class BnGraphicBufferConsumer : public SafeBnInterface<IGraphicBufferConsumer>
复制代码

它们主要是实现了两套IGraphicBufferProducerIGraphicBufferConsumerBinder接口,主要都是操做BufferQueue的相关接口,定义以下:

  • IGraphicBufferProducer
    class IGraphicBufferProducer : public IInterface
    {
    public:
        ...
        virtual status_t dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w, uint32_t h, PixelFormat format, uint64_t usage, uint64_t* outBufferAge, FrameEventHistoryDelta* outTimestamps) = 0;
        ...
        virtual status_t queueBuffer(int slot, const QueueBufferInput& input, QueueBufferOutput* output) = 0;
        ...
        virtual status_t connect(const sp<IProducerListener>& listener, int api, bool producerControlledByApp, QueueBufferOutput* output) = 0;
        virtual status_t disconnect(int api, DisconnectMode mode = DisconnectMode::Api) = 0;
        ...
    };
    复制代码
    • BufferQueueProducer类是IGraphicBufferProducer的实现
    • 使用Producer相关功能时须要先经过connect()方法创建链接
    • Producer使用完毕后须要调用disconnect()断开链接
  • IGraphicBufferConsumer
    class IGraphicBufferConsumer : public IInterface {
        public:
            ...
            virtual status_t acquireBuffer(BufferItem* buffer, nsecs_t presentWhen, uint64_t maxFrameNumber = 0) = 0;
            virtual status_t detachBuffer(int slot) = 0;
            virtual status_t attachBuffer(int* outSlot, const sp<GraphicBuffer>& buffer) = 0;
            virtual status_t releaseBuffer(int buf, uint64_t frameNumber, EGLDisplay display, EGLSyncKHR fence, const sp<Fence>& releaseFence) = 0;
            virtual status_t consumerConnect(const sp<IConsumerListener>& consumer, bool controlledByApp) = 0;
            virtual status_t consumerDisconnect() = 0;
            ...
    };
    复制代码
    • BufferQueueConsumer是接口IGraphicBufferConsumer的实现
    • 使用Consumer相关功能时,需经过consumerConnect()方法创建链接
      • 这里需传入IConsumerListener对象,这是一个回调接口
      • 当数据准备好了就会调用这个对象的onFrameAvailable()函数来通知Consumer来取数据
    • 取数据须要调用函数acquireBuffer()
    • 使用完数据后,需调用releaseBuffer()来把缓冲区归还给BufferQueueCore

BufferQueue的状态转换

前面提到BufferQueueCore类中定义了一个64项的数组mSlots

static constexpr int NUM_BUFFER_SLOTS = 64;
namespace BufferQueueDefs {
    typedef BufferSlot SlotsType[NUM_BUFFER_SLOTS];
} 
BufferQueueDefs::SlotsType mSlots;
复制代码

mSlots数组元素类型是BufferSlot,关键定义以下:

struct BufferSlot {
    ...
    sp<GraphicBuffer> mGraphicBuffer;
    ...
    BufferState mBufferState;
    ...
};
复制代码
  • mGraphicBuffer指向图像缓冲区GraphicBuffer的指针
    • GraphicBuffer对应的即是真正的图像缓存数据
  • mBufferState表示图像缓冲区的状态

BufferState定义以下:

struct BufferState {
    uint32_t mDequeueCount;
    uint32_t mQueueCount;
    uint32_t mAcquireCount;
    bool mShared;
}
复制代码

BufferState中4个变量对应的状态以下:

状态\变量 mShared mDequeueCount mQueueCount mAcquireCount
FREE false 0 0 0
DEQUEUED false 1 0 0
QUEUED false 0 1 0
ACQUIRED false 0 0 1
SHARED true any any any

状态之间的转换关系以下:
image

结合前面提到的接口,咱们看下整个状态转换过程的时序图: image

到这里,咱们已经大致了解了从SurfaceSurfaceFlinger的数据通道,dequeueBuffer()等方法的细节就不深刻分析了,其中会涉及GraphicBuffer的初始化过程,不影响咱们对总体的掌握(主要是太难了。。。。。),不过如下几点须要注意:

  • GraphicBuffer初始化时便会执行Gralloc模块的allocate()方法申请共享内存缓冲区
  • 而且在硬件设备支持FrameBuffer缓冲区的状况下,申请到的就是FrameBuffer的缓冲区

显示原理和Surface相关的内容到此结束了,还有不少不完善的地方,后面再来找补吧(又挖一坑)

关于Android图形显示的学习还剩下SurfaceFlinger和图像输出过程两部分,但愿清明节前搞定,(ง •̀_•́)ง

相关文章
相关标签/搜索