Android6.0ディスプレイシステム(2)Surface Flinger Surface作成


前のブログでは、SurfaceComposerClientでcreateSurface関数を呼び出すと、SurfaceFlingerのClientのcreateSurface関数に最後に呼び出されると分析しています.
この関数を見てみると,handleとgbpはいずれもBinderオブジェクトであり,gbpは画像バッファオブジェクトである.このhandleオブジェクトの役割は、前に説明したActivityのtokenと同様であり、Binderの一意性を利用してSurfaceに一意の識別子を生成することでもある.
status_t Client::createSurface(
        const String8& name,
        uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
        sp* handle,
        sp* 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* handle;
        sp* 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* handle,
                sp* 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() {
            result = flinger->createLayer(name, client, w, h, format, flags,
                    handle, gbp);
            return true;
        }
    };

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

この関数ではメッセージクラスMessageCreateLayerを定義し、そのオブジェクトをpostMessageSyncメソッドで送信します.このメッセージは同期的に送信されるので、関数が終了したら直接結果を返すことができます.そこでhandler関数に直接アクセスし,この関数ではSurfaceFlingerのcreateLayer関数を呼び出した.

一、Layerの作成


この関数は、転送されたflagsに基づいて、通常のLayerかぼやけたLayerかを作成します.
status_t SurfaceFlinger::createLayer(
        const String8& name,
        const sp& client,
        uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
        sp* handle, sp* gbp)
{
    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;

    switch (flags & ISurfaceComposerClient::eFXSurfaceMask) {
        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) {
        return result;
    }

    result = addClientLayer(client, *handle, *gbp, layer);
    if (result != NO_ERROR) {
        return result;
    }

    setTransactionFlags(eTransactionNeeded);
    return result;
}
まず、一般的なLayerの作成を見てみましょう.入力されたformatパラメータに基づいて、異なるフォーマットを選択します.次に、Layerを作成します.具体的なLayerについては、後述します.次にhandleとgbpを取得します.
status_t SurfaceFlinger::createNormalLayer(const sp& client,
        const String8& name, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format,
        sp* handle, sp* gbp, sp* 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;
    }

    *outLayer = new Layer(this, client, name, w, h, flags);// Layer
    status_t err = (*outLayer)->setBuffers(w, h, format, flags);
    if (err == NO_ERROR) {
        *handle = (*outLayer)->getHandle();
        *gbp = (*outLayer)->getProducer();
    }

    ALOGE_IF(err, "createNormalLayer() failed (%s)", strerror(-err));
    return err;
}
では、あいまいなLayerを見てみましょう.これは簡単で、layerDimを直接新規作成し、handleとgbpを取得します.
status_t SurfaceFlinger::createDimLayer(const sp& client,
        const String8& name, uint32_t w, uint32_t h, uint32_t flags,
        sp* handle, sp* gbp, sp* outLayer)
{
    *outLayer = new LayerDim(this, client, name, w, h, flags);
    *handle = (*outLayer)->getHandle();
    *gbp = (*outLayer)->getProducer();
    return NO_ERROR;
}

二、handleを取得する


次にhandleの取得を見てみましょう.Handleを新規作成するだけです.このHandleはBinderの実装にすぎません.Surfaceのグローバル一意性を識別し、実際の内容はありません.
sp 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 mOwner;
    public:
        Handle(const sp& flinger, const sp& layer)
            : LayerCleaner(flinger, layer), mOwner(layer) {
        }
    };

    return new Handle(mFlinger, this);
}

三、gbp画像バッファ


ではgbpの取得を見てみましょう.それはLayerのmProducerメンバー変数です.
sp Layer::getProducer() const {
    return mProducer;
}

一方、mProducerはLayerのonFirstRefに付与されており、MonitoredProducerコンストラクション関数のパラメータproducerに注目しています.実際にはMonitoredProducerはエージェントクラスにすぎず、このproducerパラメータで実装されています.BufferQueue::createBufferQueueで作成されました.
void Layer::onFirstRef() {
    // Creates a custom BufferQueue for SurfaceFlingerConsumer to use
    sp producer;
    sp consumer;
    BufferQueue::createBufferQueue(&producer, &consumer);
    mProducer = new MonitoredProducer(producer, mFlinger);
    ......

このproducerがBufferQueueProducerオブジェクトです.
void BufferQueue::createBufferQueue(sp* outProducer,
        sp* outConsumer,
        const sp& allocator) {

    sp core(new BufferQueueCore(allocator));
    sp producer(new BufferQueueProducer(core));
    sp consumer(new BufferQueueConsumer(core));

    *outProducer = producer;
    *outConsumer = consumer;
}
次のブログでは、これを分析します.