Android SurfaceFlinger 学习之路(六)----SurfaceFlinger创建Surface

2024-02-05 09:32

本文主要是介绍Android SurfaceFlinger 学习之路(六)----SurfaceFlinger创建Surface,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!


http://windrunnerlihuan.com/2017/06/17/Android-SurfaceFlinger-%E5%AD%A6%E4%B9%A0%E4%B9%8B%E8%B7%AF-%E5%85%AD-SurfaceFlinger%E5%88%9B%E5%BB%BASurface/


       这次需要了解一下SurfaceFlinger创建Surface的流程,可能比较短,因为后面GraphicBuffer管理可能会比较多。另外,应用层创建Surface以后会继续学习,并且流畅会比较长,因为设计到了WMS等等。

life

图层分析

       在分析Android应用程序请求SurfaceFlinger创建Surface之前,我们首先了解一下Surface是由什么组成的。我们可以将Surface理解为一个绘图表面,Android应用程序负责往这个绘图表面上填内容,而SurfaceFlinger服务负责将这个绘图表面的内容取出来,并且渲染在显示屏上

猜测

       每个应用程序对应着一个或者多个图形界面,而每一个界面我们称之为surface,或者说是window,如下图:

surface

       上图我们可以看到三个surface,在这里我们需要弄明白的问题是:

  1. 每个surface在屏幕上有它的位置、大小,然后每个surface 里面还有要显示的内容,内容、大小、位置 这些元素,在我们改变应用程序的时候都可能会改变,改变时应该如何处理?
  2. 然后就各个surface 之间可能有重叠,比如说在上面的简略图中,灰色覆盖了橙色,绿色覆盖了橙色 ,而且还具有一定透明度。这种层之间的关系应该如何描述?

       对于第一个问题,我们需要一个结构来记录应用程序界面的位置,大小,以及一个buffer 来记录需要显示的内容,所以这就是我们surface 的概念,surface 实际我们可以把它理解成一个容器,这个容器记录着应用程序界面的控制信息,比如说大小啊,位置啊,而它还有buffer 来专门存储需要显示的内容。
       对于第二个问题,我们可以想象在屏幕平面的垂直方向还有一个Z 轴,所有的surface 根据在Z 轴上的坐标来确定前后,这样就可以描述各个surface 之间的上下覆盖关系了,而这个在Z 轴上的顺序,图形上有个专业术语叫Z-order 。

       在这里还存在一个问题,那就是当存在图形重合的时候应该如何处理呢,而且可能有些surface 还带有透明信息,这里就是我们SurfaceFlinger 需要解决问题,它要把各个surface 组合(compose/merge) 成一个main Surface ,最后将Main Surface 的内容发送给FB,这样屏幕上就能看到我们想要的效果。

compositon

概述

       在Android中,Window与Surface一一对应。 如果说Window关心的是层次和布局,是从设计者角度定义的类,Surface则从实现角度出发,是工程师关系和考虑的类。Window的内容是变化 的,Surface需要有空间来记录每个时刻Window的内容。在Android的SurfaceFlinger实现里,通常一个Surface有两块 Buffer, 一块用于绘画,一块用于显示,两个Buffer按照固定的频率进行交换,从而实现Window的动态刷新。

       但是,在SurfaceFlinger服务这一侧,绘图表面使用Layer类来描述Layer是SurfaceFlinger 进行合成的基本操作单元。Layer在应用请求创建Surface的时候在SurfaceFlinger内部创建,因此一个Surface对应一个 Layer, 但注意,Surface不一定对应于Window,Android中有些Surface并不跟某个Window相关,而是有程序直接创建,比如说 StrictMode, 一块红色的背景,用于提示示Java代码中的一些异常, 还有SurfaceView, 用于显示有硬件输出的视频内容等。

       Each Layer has:

  • Z order
  • Alpha value from 0 to 255
  • visibleRegion
  • crop region
  • transformation: rotate 0, 90, 180, 270: flip H, V: scale

       当多个Layer进行合成的时候,并不是整个Layer的空间都会被完全显示,根据这个Layer最终的显示效果,一个Layer可以被划分成很多的Region, Android SurfaceFlinger 定义了以下一些Region类型:

  • TransparantRegion: 完全透明的区域,在它之下的区域将被显示出来。
  • OpaqueRegion: 完全不透明的区域,是否显示取决于它上面是否有遮挡或是否透明。
  • VisibleRegion: 可见区域,包括完全不透明无遮挡区域或半透明区域。 visibleRegion = Region - above OpaqueRegion.
  • CoveredRegion: 被遮挡区域,在它之上,有不透明或半透明区域。
  • DirtyRegion: 可见部分改变区域,包括新的被遮挡区域,和新的露出区域。

       Android 系统支持多种显示设备,比如说,输出到手机屏幕,或者通过WiFi 投射到电视屏幕。Android用DisplayDevice类来表示这样的设备。不是所有的Layer都会输出到所有的Display, 比如说,我们可以只将Video Layer投射到电视, 而非整个屏幕。LayerStack 就是为此设计,LayerStack 是一个Display 对象的一个数值, 而类Layer里成员State结构体也有成员变量mLayerStack, 只有两者的mLayerStack 值相同,Layer才会被输出到给该Display设备。所以LayerStack 决定了每个Display设备上可以显示的Layer数目。

       SurfaceFlinger的工作内容,就是定期检查所有Layer的参数更新(LayerStack等),计算新的DirtyRegion,然后将结果推送给底层显示驱动进行显示。这里面有很多的细节,我们将在后续会专门研究。

       上面描述的几个概念,均是针对于显示这个层面,更多是涉及到中下层模块,应用层并不参与也无需关心。对于应用而言,它关心的是如何将内容画出来。Canvas 是Java层定义的一个类,它对应与Surface上的某个区域并提供了很多的2D绘制函数(借助于底层的Skia或OpenGL)。应用只需通过 LockCanvas() 来获取一个Canvas对象,并调用它的绘画方法,然后 unLockCanvasAndPost()来通知底层将更新内容进行显示。当然,并不是所有应用程序都需要直接操作Canva, 事实上只有少量应用需要直接操作Canvas, Android提供了很多封装好的控件 Widget,应用只需提供素材,如文字,图片,属性等等,这些控件会调用Canvas提供的接口帮用户完成绘制工作。

       SurfaceFlinger 是一个独立的Service, 它接收所有Window的Surface作为输入,根据Z-Order, 透明度,大小,位置等参数,计算出每个Surface在最终合成图像中的位置,然后交由HWComposer或OpenGL生成最终的显示Buffer, 然后显示到特定的显示设备上。

Surface创建流程

SurfaceFlinger服务侧Layer创建

       上面我们提,到在SurfaceFlinger服务这一侧,绘图表面使用Layer类来描述

Layer

       Layer类内部定义了两个结构体Geometry、State,位于frameworks/native/services/surfaceflinger/Layer.h中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
struct Geometry {
    uint32_t w;
    uint32_t h;
    Rect crop;
    inline bool operator ==(const Geometry& rhs) const {
        return (w == rhs.w && h == rhs.h && crop == rhs.crop);
    }
    inline bool operator !=(const Geometry& rhs) const {
        return !operator ==(rhs);
    }
};

struct State {
    Geometry active;
    Geometry requested;
    uint32_t z;
    uint32_t layerStack;
    uint8_t alpha;
    uint8_t flags;
    uint8_t reserved[2];
    int32_t sequence; // changes when visible regions can change
    Transform transform;
    // the transparentRegion hint is a bit special, it's latched only
    // when we receive a buffer -- this is because it's "content"
    // dependent.
    Region activeTransparentRegion;
    Region requestedTransparentRegion;
};

       用变量mCurrentState和mDrawingState连个类型为State的成员变量保存当前和上一次的绘制状态,记录大小、可视区域、透明度、标志位、z-order等信息。

       我们可以回顾一下以前 Android SurfaceFlinger 学习之路(三)—-Android开机动画流程简述 ,开机动画中创建surface流程位于BootAnimation.cpp的readyToRun函数,位于frameworks/base/cmds/bootanimation/BootAnimation.cpp中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
status_t BootAnimation::readyToRun() {
    ......
    // create the native surface
    sp<SurfaceControl> control = session()->createSurface(String8("BootAnimation"),
            dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565);

    SurfaceComposerClient::openGlobalTransaction();
    control->setLayer(0x40000000);
    SurfaceComposerClient::closeGlobalTransaction();

    sp<Surface> s = control->getSurface();
   
    ......
}

sp<SurfaceComposerClient> BootAnimation::session() const {
    return mSession;
}
BootAnimation::BootAnimation() : Thread(false), mZip(NULL)
{
    mSession = new SurfaceComposerClient();
}

       这里session函数返回一个SurfaceComposerClient对象,在Android SurfaceFlinger 学习之路(四)—-SurfaceFlinger服务的启动与连接过程一文中,我们已经看到过SurfaceComposerClient类的作用了,Android应用程序主要就是通过它来和SurfaceFlinger服务建立连接的,连接的结果就是得到一个类型为Client的Binder代理对象,保存它的成员变量mClient中。

       我们查看SurfaceComposerClient的createSurface函数,位于frameworks/native/libs/gui/SurfaceComposerClient.cpp中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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;
        //我们先分析这里,里面有创建Layer的部分
        status_t err = mClient->createSurface(name, w, h, format, flags,
                &handle, &gbp);
        ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err));
        if (err == NO_ERROR) {
            sur = new SurfaceControl(this, handle, gbp);
        }
    }
    return sur;
}

       因此又要到Client的createSurface函数中,位于frameworks/native/services/surfaceflinger/Client.cpp中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
status_t Client::createSurface(
        const String8& name,
        uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
        sp<IBinder>* handle,
        sp<IGraphicBufferProducer>* gbp)
{
    /*
     * createSurface must be called from the GL thread so that it can
     * have access to the GL context.
     */

    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; }
        virtual bool handler() {
            //给SurfaceFlinger的MessageQueue发送同步消息,createLayer函数被调用
            result = flinger->createLayer(name, client, w, h, format, flags,
                    handle, gbp);
            return true;
        }
    };

    sp<MessageBase> msg = new MessageCreateLayer(mFlinger.get(),
            name, this, w, h, format, flags, handle, gbp);
    mFlinger->postMessageSync(msg);
    return static_cast<MessageCreateLayer*>( msg.get() )->getResult();
}

       给SurfaceFlinger的MessageQueue发送同步消息,createLayer函数被调用,位于frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
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)
{
    //ALOGD("createLayer for (%d x %d), name=%s", w, h, name.string());
    if (int32_t(w|h) < 0) {
        ALOGE("createLayer() failed, w or h is negative (w=%d, h=%d)",
                int(w), int(h));
        return BAD_VALUE;
    }

    status_t result = NO_ERROR;

    sp<Layer> layer;

    switch (flags & ISurfaceComposerClient::eFXSurfaceMask) {
        case ISurfaceComposerClient::eFXSurfaceNormal:
            //创建普通的Layer
            result = createNormalLayer(client,
                    name, w, h, flags, format,
                    handle, gbp, &layer);
            break;
        case ISurfaceComposerClient::eFXSurfaceDim:
            创建模糊的Layer
            result = createDimLayer(client,
                    name, w, h, flags,
                    handle, gbp, &layer);
            break;
        default:
            result = BAD_VALUE;
            break;
    }

    if (result == NO_ERROR) {
        //将创建的Layer按顺序添加进list中,我们以后讲z-order会讲
        addClientLayer(client, *handle, *gbp, layer);
        //修改标志位
        setTransactionFlags(eTransactionNeeded);
    }
    return result;
}

       这里会根据传进来的flag判断创建什么类型的Layer,一个是普通的,一个是模糊的Layer。这里我们只看看普通的Layer,createNormalLayer函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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)
{
    // initialize the surfaces
    switch (format) {//像素格式
    case PIXEL_FORMAT_TRANSPARENT:
    case PIXEL_FORMAT_TRANSLUCENT:
        format = PIXEL_FORMAT_RGBA_8888;
        break;
    case PIXEL_FORMAT_OPAQUE:
        format = PIXEL_FORMAT_RGBX_8888;
        break;
    }
    //创建一个Layer对象
    *outLayer = new Layer(this, client, name, w, h, flags);
    //调用Layer的setBuffers函数,这只一些变量
    status_t err = (*outLayer)->setBuffers(w, h, format, flags);
    if (err == NO_ERROR) {
        //给成员变量handle和gbp赋值
        *handle = (*outLayer)->getHandle();
        *gbp = (*outLayer)->getProducer();
    }

    ALOGE_IF(err, "createNormalLayer() failed (%s)", strerror(-err));
    return err;
}

       这里创建了一个Layer对象,我们可以看看Layer的构造函数,位于frameworks/native/services/surfaceflinger/Layer.cpp中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client,
        const String8& name, uint32_t w, uint32_t h, uint32_t flags)
    :   contentDirty(false),
        sequence(uint32_t(android_atomic_inc(&sSequence))),
        mFlinger(flinger),
        mTextureName(-1U),
        mPremultipliedAlpha(true),
        mName("unnamed"),
        mDebug(false),
        mFormat(PIXEL_FORMAT_NONE),
        mTransactionFlags(0),
        mQueuedFrames(0),
        mSidebandStreamChanged(false),
        mCurrentTransform(0),
        mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
        mCurrentOpacity(true),
        mRefreshPending(false),
        mFrameLatencyNeeded(false),
        mFiltering(false),
        mNeedsFiltering(false),
        mMesh(Mesh::TRIANGLE_FAN, 4, 2, 2),
        mSecure(false),
        mProtectedByApp(false),
        mHasSurface(false),
        mClientRef(client),
        mPotentialCursor(false)
{
    mCurrentCrop.makeInvalid();
    mFlinger->getRenderEngine().genTextures(1, &mTextureName);
    mTexture.init(Texture::TEXTURE_EXTERNAL, mTextureName);

    uint32_t layerFlags = 0;
    if (flags & ISurfaceComposerClient::eHidden)
        layerFlags |= layer_state_t::eLayerHidden;
    if (flags & ISurfaceComposerClient::eOpaque)
        layerFlags |= layer_state_t::eLayerOpaque;

    if (flags & ISurfaceComposerClient::eNonPremultiplied)
        mPremultipliedAlpha = false;

    mName = name;

    mCurrentState.active.w = w;
    mCurrentState.active.h = h;
    mCurrentState.active.crop.makeInvalid();
    mCurrentState.z = 0;
    mCurrentState.alpha = 0xFF;
    mCurrentState.layerStack = 0;
    mCurrentState.flags = layerFlags;
    mCurrentState.sequence = 0;
    mCurrentState.transform.set(0, 0);
    mCurrentState.requested = mCurrentState.active;

    // drawing state & current state are identical
    mDrawingState = mCurrentState;

    nsecs_t displayPeriod =
            flinger->getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);
    mFrameTracker.setDisplayRefreshPeriod(displayPeriod);
}

       Layer的构造函数中就是给一些变量赋了初值,事情不多。
       我们从上面的类图看到Layer间接继承于RefBase类,所以对象第一次被赋值给强指针会调用onFirstRef函数,我们看看它里面做了那些事情:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
void Layer::onFirstRef() {
    // Creates a custom BufferQueue for SurfaceFlingerConsumer to use
    sp<IGraphicBufferProducer> producer;
    sp<IGraphicBufferConsumer> consumer;
    //BufferQueue创建图形缓冲区管理成员,我们以后分析图形缓冲区管理会讲到
    BufferQueue::createBufferQueue(&producer, &consumer);
    //mProducer 不为空了,赋值
    mProducer = new MonitoredProducer(producer, mFlinger);
    //mSurfaceFlingerConsumer 不为空了,赋值
    mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(consumer, mTextureName);
    //设置消费者相关设置
    mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0));
    mSurfaceFlingerConsumer->setContentsChangedListener(this);
    mSurfaceFlingerConsumer->setName(mName);
    
// TARGET_DISABLE_TRIPLE_BUFFERING为false,所以使用了三缓冲,project butter计划嘛
#ifdef TARGET_DISABLE_TRIPLE_BUFFERING
#warning "disabling triple buffering"
    mSurfaceFlingerConsumer->setDefaultMaxBufferCount(2);
#else
    mSurfaceFlingerConsumer->setDefaultMaxBufferCount(3);
#endif
    //获取默认显示器
    const sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice());
    //更新显示图像方向
    updateTransformHint(hw);
}

       onFirstRef函数中做的事情主要是创建图形缓冲区管理成员相关,这个我们后面会讲到。
       然后就是根据“黄油计划”定义了三缓冲,以及显示器方向的调整。

       Layer对象创建完后,就调用Layer的setBuffers函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
status_t Layer::setBuffers( uint32_t w, uint32_t h,
                            PixelFormat format, uint32_t flags)
{
    uint32_t const maxSurfaceDims = min(
            mFlinger->getMaxTextureSize(), mFlinger->getMaxViewportDims());

    // never allow a surface larger than what our underlying GL implementation
    // can handle.
    if ((uint32_t(w)>maxSurfaceDims) || (uint32_t(h)>maxSurfaceDims)) {
        ALOGE("dimensions too large %u x %u", uint32_t(w), uint32_t(h));
        return BAD_VALUE;
    }

    mFormat = format;

    mPotentialCursor = (flags & ISurfaceComposerClient::eCursorWindow) ? true : false;
    mSecure = (flags & ISurfaceComposerClient::eSecure) ? true : false;
    mProtectedByApp = (flags & ISurfaceComposerClient::eProtectedByApp) ? true : false;
    mCurrentOpacity = getOpacityForFormat(format);

    mSurfaceFlingerConsumer->setDefaultBufferSize(w, h);
    mSurfaceFlingerConsumer->setDefaultBufferFormat(format);
    mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0));

    return NO_ERROR;
}

       这里也是一些变量的设置,东西不多。
       然后就是给gbp和handle赋值。gbp已经不为空了,我们在onFirstRef函数中对它付了值。那么我们看看给handle赋值,Layer的getHandle函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
sp<IBinder> Layer::getHandle() {
    Mutex::Autolock _l(mLock);

    LOG_ALWAYS_FATAL_IF(mHasSurface,
            "Layer::getHandle() has already been called");

    mHasSurface = true;

    /*
     * The layer handle is just a BBinder object passed to the client
     * (remote process) -- we don't keep any reference on our side such that
     * the dtor is called when the remote side let go of its reference.
     *
     * LayerCleaner ensures that mFlinger->onLayerDestroyed() is called for
     * this layer when the handle is destroyed.
     */

    class Handle : public BBinder, public LayerCleaner {
        wp<const Layer> mOwner;
    public:
        Handle(const sp<SurfaceFlinger>& flinger, const sp<Layer>& layer)
            : LayerCleaner(flinger, layer), mOwner(layer) {
        }
    };

    return new Handle(mFlinger, this);
}

       只是新建一个Handle,而这个Handle只是一个Binder的实现,就是标识Surface的全局唯一性,没有什么实际的内容。

       上述就是Layer的创建,是基于SurfaceFlinger服务端这一侧。

应用侧Surface创建

       我们继续回到上面的SurfaceComposerClient的createSurface函数,为了不往上翻我再贴一遍:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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;
        //上面分析完了SurfaceFlinger创建完了一个Layer
        status_t err = mClient->createSurface(name, w, h, format, flags,
                &handle, &gbp);
        ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err));
        if (err == NO_ERROR) {
            //根据上面创建Layer时创建的handle和gbp再创建一个SurfaceControl,并返回
            sur = new SurfaceControl(this, handle, gbp);
        }
    }
    return sur;
}

       上面分析完了SurfaceFlinger创建完了一个Layer,接着根据上面创建Layer时创建的handle和gbp再创建一个SurfaceControl,并返回。

SurfaceControl创建

       在Android应用程序这一侧,每一个绘图表面都使用一个Surface对象来描述,每一个Surface对象都是由一个SurfaceControl对象来创建的。Surface类和SurfaceControl类的关系以及实现如图所示:

SurfaceControl

       SurfaceControl类的成员变量mClient是一个类型为SurfaceComposerClient对象,在Android SurfaceFlinger 学习之路(四)—-SurfaceFlinger服务的启动与连接过程一文中,我们已经看到过SurfaceComposerClient类的作用了,Android应用程序主要就是通过它来和SurfaceFlinger服务建立连接的,连接的结果就是得到一个类型为Client的Binder代理对象,保存它的成员变量mClient中。

       SurfaceControl类的成员变量mHandle是指向的就是我们上面分析的创建Layer时,最后将Layer和SurfaceFlinger作为构造函数的参数创建一个Handle对象,这个Handle是一个Binder的实现,就是标识Surface的全局唯一性。当Android应用程序请求SurfaceFlinger服务创建一个绘图表面的时候,SurfaceFlinger服务就会在内部创建一个Layer对象,然后将Layer和SurfaceFlinger包装成一个Handle的一个Binder代理对象返回来给Android应用程序,然后Android应用程序再将这个Binder代理对象保存在一个SurfaceControl对象的成员变量mHandle中。

       SurfaceControl类的成员变量mSurfaceData是一个类型为Surface的强指针,它指向了一个Surface对象。

       SurfaceControl的构造函数也比较简单,位于frameworks/native/libs/gui/SurfaceControl.cpp中:

1
2
3
4
5
6
7
SurfaceControl::SurfaceControl(
        const sp<SurfaceComposerClient>& client,
        const sp<IBinder>& handle,
        const sp<IGraphicBufferProducer>& gbp)
    : mClient(client), mHandle(handle), mGraphicBufferProducer(gbp)
{
}

       SurfaceControl类创建就到这里。

       附:这是native层的SurfaceControl,对于java层,也有一个SurfaceControl,Android 4.3 里新引进的类。Google从之前的Surface类里拆出部分接口,变成SurfaceControl,为什么要这样?为了让结构更清晰,WindowManagerService 只能对Surface进行控制,但并不更新Surface里的内容,分拆之后,WindowManagerService 只能访问SurfaceControl,它主要控制Surface的创建,销毁,Z-order,透明度,显示或隐藏,等等。而真正的更新者,View会通过Canvas的接口将内容画到Surface上。那View怎么拿到WMService创建的Surface,答案是outSurface.copyFrom(surfaceControl);,surfaceControl 被转换成一个Surface对象,然后传回给ViewRoot, 前面创建的空的Surface现在有了实质内容。Surface通过这种方式被创建出来,Surface对应的Buffer 也相应的在SurfaceFlinger内部通过HAL层模块(GRAlloc)分配并维护在SurfaceFlinger 内部,Canvas() 通过dequeueBuffer()接口拿到Surface的一个Buffer,绘制完成后通过queueBuffer()还给SurfaceFlinger进行绘制。(这一部分我们后期学习WMS时候再分析

Surface创建

       从上面的类图,可以看到Surface类的成员变量mGraphicBufferProducer指向一个sp< IGraphicBufferProducer > 类型的对象,在Layer的onFirstRef函数中,mProducer复制后,类型为MonitoredProducer,将它有传给了Surface中。我们注意MonitoredProducer构造函数的一个参数producer,事实上MonitoredProducer只是一个代理类,真正的实现在这个producer参数。它是在BufferQueue::createBufferQueue中创造的。这个我们下一篇会分析这个。

       Surface类继承了ANativeObjectBase类,而ANativeObjectBase类又继承了ANativeWindow类。我们知道,Android系统是通过OpenGL库来绘制UI的。OpenGL库在绘制UI的时候,需要底层的系统提供一个本地窗口给它,以便它可以将UI绘制在这个本地窗口上。Android系统为OpenGL库定提供的本地窗口使用ANativeWindow类来描述,Surface类通过ANativeObjectBase类间接地继承了ANativeWindow类,因此,Surface类也是用来描述OpenGL绘图所需要的一个本地窗口的。从这个角度出发,我们可以将Surface类看作OpenGL库与Android的UI系统之间的一个桥梁。

       创建Surface的函数也很简单,查看SurfaceControl的getSurface函数:

1
2
3
4
5
6
7
8
9
10
sp<Surface> SurfaceControl::getSurface() const
{
    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);
    }
    return mSurfaceData;
}

       以及看看Surface的构造函数,位于frameworks/native/libs/gui/Surface.cpp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
Surface::Surface(
        const sp<IGraphicBufferProducer>& bufferProducer,
        bool controlledByApp)
    : mGraphicBufferProducer(bufferProducer)
{
    // Initialize the ANativeWindow function pointers.
    ANativeWindow::setSwapInterval  = hook_setSwapInterval;
    ANativeWindow::dequeueBuffer    = hook_dequeueBuffer;
    ANativeWindow::cancelBuffer     = hook_cancelBuffer;
    ANativeWindow::queueBuffer      = hook_queueBuffer;
    ANativeWindow::query            = hook_query;
    ANativeWindow::perform          = hook_perform;

    ANativeWindow::dequeueBuffer_DEPRECATED = hook_dequeueBuffer_DEPRECATED;
    ANativeWindow::cancelBuffer_DEPRECATED  = hook_cancelBuffer_DEPRECATED;
    ANativeWindow::lockBuffer_DEPRECATED    = hook_lockBuffer_DEPRECATED;
    ANativeWindow::queueBuffer_DEPRECATED   = hook_queueBuffer_DEPRECATED;

    const_cast<int&>(ANativeWindow::minSwapInterval) = 0;
    const_cast<int&>(ANativeWindow::maxSwapInterval) = 1;

    mReqWidth = 0;
    mReqHeight = 0;
    mReqFormat = 0;
    mReqUsage = 0;
    mTimestamp = NATIVE_WINDOW_TIMESTAMP_AUTO;
    mCrop.clear();
    mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
    mTransform = 0;
    mStickyTransform = 0;
    mDefaultWidth = 0;
    mDefaultHeight = 0;
    mUserWidth = 0;
    mUserHeight = 0;
    mTransformHint = 0;
    mConsumerRunningBehind = false;
    mConnectedToCpu = false;
    mProducerControlledByApp = controlledByApp;
    mSwapIntervalZero = false;
}

       主要是设置了一些钩子方法,用于创建GraphicBuffer等等。还有一些变量的初始化。所以重点应该在这些钩子方法当中,我们下一节会分析。

小结

       本节我们主要讲了SurfaceFlinger创建Surface的过程,文章末尾我们我发现管理图形缓冲区的一个重要工具:BufferQueue。我们下一节会分析这个。







这篇关于Android SurfaceFlinger 学习之路(六)----SurfaceFlinger创建Surface的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/680490

相关文章

ESP32 esp-idf esp-adf环境安装及.a库创建与编译

简介 ESP32 功能丰富的 Wi-Fi & 蓝牙 MCU, 适用于多样的物联网应用。使用freertos操作系统。 ESP-IDF 官方物联网开发框架。 ESP-ADF 官方音频开发框架。 文档参照 https://espressif-docs.readthedocs-hosted.com/projects/esp-adf/zh-cn/latest/get-started/index

51单片机学习记录———定时器

文章目录 前言一、定时器介绍二、STC89C52定时器资源三、定时器框图四、定时器模式五、定时器相关寄存器六、定时器练习 前言 一个学习嵌入式的小白~ 有问题评论区或私信指出~ 提示:以下是本篇文章正文内容,下面案例可供参考 一、定时器介绍 定时器介绍:51单片机的定时器属于单片机的内部资源,其电路的连接和运转均在单片机内部完成。 定时器作用: 1.用于计数系统,可

问题:第一次世界大战的起止时间是 #其他#学习方法#微信

问题:第一次世界大战的起止时间是 A.1913 ~1918 年 B.1913 ~1918 年 C.1914 ~1918 年 D.1914 ~1919 年 参考答案如图所示

[word] word设置上标快捷键 #学习方法#其他#媒体

word设置上标快捷键 办公中,少不了使用word,这个是大家必备的软件,今天给大家分享word设置上标快捷键,希望在办公中能帮到您! 1、添加上标 在录入一些公式,或者是化学产品时,需要添加上标内容,按下快捷键Ctrl+shift++就能将需要的内容设置为上标符号。 word设置上标快捷键的方法就是以上内容了,需要的小伙伴都可以试一试呢!

AssetBundle学习笔记

AssetBundle是unity自定义的资源格式,通过调用引擎的资源打包接口对资源进行打包成.assetbundle格式的资源包。本文介绍了AssetBundle的生成,使用,加载,卸载以及Unity资源更新的一个基本步骤。 目录 1.定义: 2.AssetBundle的生成: 1)设置AssetBundle包的属性——通过编辑器界面 补充:分组策略 2)调用引擎接口API

Javascript高级程序设计(第四版)--学习记录之变量、内存

原始值与引用值 原始值:简单的数据即基础数据类型,按值访问。 引用值:由多个值构成的对象即复杂数据类型,按引用访问。 动态属性 对于引用值而言,可以随时添加、修改和删除其属性和方法。 let person = new Object();person.name = 'Jason';person.age = 42;console.log(person.name,person.age);//'J

大学湖北中医药大学法医学试题及答案,分享几个实用搜题和学习工具 #微信#学习方法#职场发展

今天分享拥有拍照搜题、文字搜题、语音搜题、多重搜题等搜题模式,可以快速查找问题解析,加深对题目答案的理解。 1.快练题 这是一个网站 找题的网站海量题库,在线搜题,快速刷题~为您提供百万优质题库,直接搜索题库名称,支持多种刷题模式:顺序练习、语音听题、本地搜题、顺序阅读、模拟考试、组卷考试、赶快下载吧! 2.彩虹搜题 这是个老公众号了 支持手写输入,截图搜题,详细步骤,解题必备

《offer来了》第二章学习笔记

1.集合 Java四种集合:List、Queue、Set和Map 1.1.List:可重复 有序的Collection ArrayList: 基于数组实现,增删慢,查询快,线程不安全 Vector: 基于数组实现,增删慢,查询快,线程安全 LinkedList: 基于双向链实现,增删快,查询慢,线程不安全 1.2.Queue:队列 ArrayBlockingQueue:

硬件基础知识——自学习梳理

计算机存储分为闪存和永久性存储。 硬盘(永久存储)主要分为机械磁盘和固态硬盘。 机械磁盘主要靠磁颗粒的正负极方向来存储0或1,且机械磁盘没有使用寿命。 固态硬盘就有使用寿命了,大概支持30w次的读写操作。 闪存使用的是电容进行存储,断电数据就没了。 器件之间传输bit数据在总线上是一个一个传输的,因为通过电压传输(电流不稳定),但是电压属于电势能,所以可以叠加互相干扰,这也就是硬盘,U盘

Eclipse+ADT与Android Studio开发的区别

下文的EA指Eclipse+ADT,AS就是指Android Studio。 就编写界面布局来说AS可以边开发边预览(所见即所得,以及多个屏幕预览),这个优势比较大。AS运行时占的内存比EA的要小。AS创建项目时要创建gradle项目框架,so,创建项目时AS比较慢。android studio基于gradle构建项目,你无法同时集中管理和维护多个项目的源码,而eclipse ADT可以同时打开