ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

AndroidQ 图形系统(2)生产者-消费者模型

2020-06-05 15:06:57  阅读:397  来源: 互联网

标签:ProxyConsumerListener 图形系统 const 生产者 sp AndroidQ ConsumerBase listener BufferQue


上一篇文章分析了上层Window创建之后,native层会创建对应的Surface,以及SurfaceFlinger进程会创建对应Layer,所以应用层的窗口对应到SurfaceFlinger进程其实就是Layer

AndroidQ上SurfaceFlinger能够创建四种类型的LayerBufferQueueLayerBufferStateLayerColorLayerContainerLayer,最常用的就是BufferQueueLayer

在创建BufferQueueLayer同时会创建一套生产者-消费者模型架构,核心是三个类:
IGraphicBufferProducer(生产者),
IGraphicBufferConsumer(消费者),
BufferQueue(buffer队列),
生产者提供图形数据,放入BufferQueue,消费者拿到图形数据进行合成,通常认为生产者为Surface,消费者为SurfaceFlinger,这篇文章就来分析一下生产者-消费者模型架构的搭建。
我们以BufferQueueLayer的创建为入口分析

BufferQueueLayer::onFirstRef

void BufferQueueLayer::onFirstRef() {
    BufferLayer::onFirstRef();

    sp<IGraphicBufferProducer> producer;
    sp<IGraphicBufferConsumer> consumer;
    //步骤1
    BufferQueue::createBufferQueue(&producer, &consumer, true);
    //步骤2
    mProducer = new MonitoredProducer(producer, mFlinger, this);
    {
        // Grab the SF state lock during this since it's the only safe way to access RenderEngine
        Mutex::Autolock lock(mFlinger->mStateLock);
        //步骤3
        mConsumer =
                new BufferLayerConsumer(consumer, mFlinger->getRenderEngine(), mTextureName, this);
    }
    //步骤4
    mConsumer->setConsumerUsageBits(getEffectiveUsage(0));
    //步骤5
    mConsumer->setContentsChangedListener(this);
    mConsumer->setName(mName);

    // BufferQueueCore::mMaxDequeuedBufferCount is default to 1
    if (!mFlinger->isLayerTripleBufferingDisabled()) {
        mProducer->setMaxDequeuedBufferCount(2);
    }

    if (const auto display = mFlinger->getDefaultDisplayDevice()) {
        updateTransformHint(display);
    }

    if (mFlinger->mLayerExt) {
        mLayerType = mFlinger->mLayerExt->getLayerClass(mName.string());
    }
}

上面这个函数就是创建SurfaceFlinger生产者-消费者模型的核心代码,先看步骤1:createBufferQueue,从名字看就能知道是创建BufferQueue,并且将生产者producer和消费者consumer的地址传了过去,显然这两个对象也会在createBufferQueue中创建

createBufferQueue

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;
}

可以看到这个函数中并没有创建BufferQueue,而是创建的BufferQueueCore,可见BufferQueue的核心实现其实是依靠BufferQueueCore的,接着又创建了生产者的具体实现类BufferQueueProducer,消费者的具体实现类BufferQueueConsumer,并且这两个类都持有BufferQueueCore的引用,最后outProduceroutConsumer分别指向创建的生产者-消费者

我们再来看看BufferQueue中有一个很重要的监听器ProxyConsumerListener

 class ProxyConsumerListener : public BnConsumerListener {
    public:
        explicit ProxyConsumerListener(const wp<ConsumerListener>& consumerListener);
        ~ProxyConsumerListener() override;
        void onDisconnect() override;
        void onFrameAvailable(const BufferItem& item) override;
        void onFrameReplaced(const BufferItem& item) override;
        void onBuffersReleased() override;
        void onSidebandStreamChanged() override;
        void addAndGetFrameTimestamps(
                const NewFrameEventsEntry* newTimestamps,
                FrameEventHistoryDelta* outDelta) override;
    private:
        // mConsumerListener is a weak reference to the IConsumerListener.  This is
        // the raison d'etre of ProxyConsumerListener.
        wp<ConsumerListener> mConsumerListener;
    };

ProxyConsumerListener的最终父类是ConsumerListener,从名字能看出来ProxyConsumerListener是一个代理端,那么ConsumerListener的具体实现端在哪里呢?这个问题我们接着分析代码再看

步骤1的createBufferQueue函数已经看完了,接着看看步骤2:

mProducer = new MonitoredProducer(producer, mFlinger, this);

为生产者对象创建一个MonitoredProducer,这个类完全就是生产者的封装类,它里面的所有函数几乎都是通过传递进去的producer来完成的:

status_t MonitoredProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
    return mProducer->cancelBuffer(slot, fence);
}

int MonitoredProducer::query(int what, int* value) {
    return mProducer->query(what, value);
}

status_t MonitoredProducer::connect(const sp<IProducerListener>& listener,
        int api, bool producerControlledByApp, QueueBufferOutput* output) {
    return mProducer->connect(listener, api, producerControlledByApp, output);
}

status_t MonitoredProducer::disconnect(int api, DisconnectMode mode) {
    return mProducer->disconnect(api, mode);
}

status_t MonitoredProducer::setSidebandStream(const sp<NativeHandle>& stream) {
    return mProducer->setSidebandStream(stream);
}

void MonitoredProducer::allocateBuffers(uint32_t width, uint32_t height,
        PixelFormat format, uint64_t usage) {
    mProducer->allocateBuffers(width, height, format, usage);
}

status_t MonitoredProducer::allowAllocation(bool allow) {
    return mProducer->allowAllocation(allow);
}

再接着看看步骤3:

mConsumer =
	new BufferLayerConsumer(consumer, mFlinger->getRenderEngine(), mTextureName, this);

这是为消费者创建包装类,先来看看BufferLayerConsumer这个类,继承ConsumerBase

class BufferLayerConsumer : public ConsumerBase

同时在初始化BufferLayerConsumer时调用了父类ConsumerBase的构造函数,将消费者对象传递了过去

BufferLayerConsumer::BufferLayerConsumer(const sp<IGraphicBufferConsumer>& bq,
                                         renderengine::RenderEngine& engine, uint32_t tex,
                                         Layer* layer)
      : ConsumerBase(bq, false),
      ......
      }

ConsumerBase是个重点,来看看:

class ConsumerBase : public virtual RefBase,
        protected ConsumerListener {

看到没有,继承ConsumerListener,前面我们说ProxyConsumerListener的最终父类是ConsumerListener,是作为代理端,那么ConsumerBase很可能就是具体实现端了,而ConsumerBase中又有BufferQueueConsumer消费者对象,所以ConsumerListener的一些具体实现是需要依靠BufferQueueConsumer的,比如onBuffersReleased函数,
ConsumerBase中还有一个比较重要的结构体监听器FrameAvailableListener

struct FrameAvailableListener : public virtual RefBase {
        // See IConsumerListener::onFrame{Available,Replaced}
        virtual void onFrameAvailable(const BufferItem& item) = 0;
        virtual void onFrameReplaced(const BufferItem& /* item */) {}
    };

这个监听器中有两个和ConsumerListener同名的函数,我们看看ConsumerBase对这两个函数的实现:

void ConsumerBase::onFrameAvailable(const BufferItem& item) {
    CB_LOGV("onFrameAvailable");

    sp<FrameAvailableListener> listener;
    { // scope for the lock
        Mutex::Autolock lock(mFrameAvailableMutex);
        listener = mFrameAvailableListener.promote();
    }

    if (listener != nullptr) {
        CB_LOGV("actually calling onFrameAvailable");
        listener->onFrameAvailable(item);
    }
}

void ConsumerBase::onFrameReplaced(const BufferItem &item) {
    CB_LOGV("onFrameReplaced");

    sp<FrameAvailableListener> listener;
    {
        Mutex::Autolock lock(mFrameAvailableMutex);
        listener = mFrameAvailableListener.promote();
    }

    if (listener != nullptr) {
        CB_LOGV("actually calling onFrameReplaced");
        listener->onFrameReplaced(item);
    }
}

可以看到,ConsumerBase中这个两个函数具体实现就是调用
FrameAvailableListener的这两个函数,但现在暂时还不知道ConsumerBaseFrameAvailableListener从哪里传递过来的,以及FrameAvailableListener是由哪个类实现的

我们继续看看ConsumerBase的构造函数:

ConsumerBase::ConsumerBase(const sp<IGraphicBufferConsumer>& bufferQueue, bool controlledByApp) :
        mAbandoned(false),
        mConsumer(bufferQueue),
        mPrevFinalReleaseFence(Fence::NO_FENCE) {
   	 	...
    wp<ConsumerListener> listener = static_cast<ConsumerListener*>(this);
    sp<IConsumerListener> proxy = new BufferQueue::ProxyConsumerListener(listener);

    status_t err = mConsumer->consumerConnect(proxy, controlledByApp);
		...
}

这里面创建了一个 BufferQueue::ProxyConsumerListener对象,并将ConsumerBase传递了过去,所以这里我们能确定了代理端 BufferQueue::ProxyConsumerListener的具体实现端就是ConsumerBase,接着调用了BufferQueueConsumer消费者的consumerConnect函数,又将BufferQueue::ProxyConsumerListener传递了过去,consumerConnect实现在BufferQueueConsumer.h中:

virtual status_t consumerConnect(const sp<IConsumerListener>& consumer,
            bool controlledByApp) {
        return connect(consumer, controlledByApp);
    }

又调用了自己的connect函数,这个函数实现在BufferQueueConsumer.cpp中:

status_t BufferQueueConsumer::connect(
        const sp<IConsumerListener>& consumerListener, bool controlledByApp) {
    ATRACE_CALL();

    if (consumerListener == nullptr) {
        BQ_LOGE("connect: consumerListener may not be NULL");
        return BAD_VALUE;
    }

    BQ_LOGV("connect: controlledByApp=%s",
            controlledByApp ? "true" : "false");

    std::lock_guard<std::mutex> lock(mCore->mMutex);

    if (mCore->mIsAbandoned) {
        BQ_LOGE("connect: BufferQueue has been abandoned");
        return NO_INIT;
    }

    mCore->mConsumerListener = consumerListener;
    mCore->mConsumerControlledByApp = controlledByApp;

    return NO_ERROR;
}

看到了吗,从ConsumerBase传递过来的 BufferQueue::ProxyConsumerListener最终赋值给了
BufferQueueCoremConsumerListener,由此可知BufferQueue果然是一个空壳

监听器传来传去确实容易混乱,我们来总结一下监听器的调用流程,前面createBufferQueue中创建了BufferQueueCoreBufferQueueProducerBufferQueueConsumer,并且生产者-消费者都持有BufferQueueCore的引用,那么当生产者有消息需要通知消费者时流程就是这样:
生产者调用BufferQueueCoremConsumerListener某个监听函数,mConsumerListener调到了 BufferQueue::ProxyConsumerListener的同名监听函数, BufferQueue::ProxyConsumerListener这个类创建时接收了ConsumerListener的具体实现类ConsumerBase,所以调到了ConsumerBase的同名监听函数,ConsumerBase中又有消费者对象,所以又可以根据情况调到消费者中去,这样就实现了消费者对生产者的监听

到这里还剩下FrameAvailableListener监听器的具体实现类没有看到

接着分析代码,步骤1,2,3已经分析完了,步骤4没什么分析的,我们看看步骤5:

mConsumer->setContentsChangedListener(this);

通过setContentsChangedListener给消费者设置一个监听器,并且传递的是this,我们先看看当前类继承了哪个监听器,当前类是BufferQueueLayer别忘了:

class BufferQueueLayer : public BufferLayer, 
						 public BufferLayerConsumer::ContentsChangedListener {}

继承的是BufferLayerConsumer::ContentsChangedListener,继续看:

class BufferLayerConsumer : public ConsumerBase {
public:
    	......
    struct ContentsChangedListener : public FrameAvailableListener {
        virtual void onSidebandStreamChanged() = 0;
    };

看到这里应该恍然大悟了,原来FrameAvailableListener的具体实现类是BufferQueueLayer,再回到setContentsChangedListener函数:

void BufferLayerConsumer::setContentsChangedListener(const wp<ContentsChangedListener>& listener) {
    setFrameAvailableListener(listener);
    Mutex::Autolock lock(mMutex);
    mContentsChangedListener = listener;
}

调用setFrameAvailableListener将这个监听器继续传递,这个函数BufferLayerConsumer并没有实现,调用的还是父类ConsumerBase的:

void ConsumerBase::setFrameAvailableListener(
        const wp<FrameAvailableListener>& listener) {
    CB_LOGV("setFrameAvailableListener");
    Mutex::Autolock lock(mFrameAvailableMutex);
    mFrameAvailableListener = listener;
}

这个函数仅仅是将传递过来的监听器保存在自己的成员变量mFrameAvailableListener中,以便由生产者那边进行调用,另外setContentsChangedListener中同样将监听器保存在了BufferLayerConsumer的成员变量mContentsChangedListener中,
我们再来总结一下FrameAvailableListener中的onFrameAvailable函数的回调流程:
生产者dequeue一块buffer,应用程序进行绘制,绘制完成后queue此块buffer,此时生产者调用BufferQueueCoremConsumerListeneronFrameAvailable回调函数,mConsumerListener其实是BufferQueue::ProxyConsumerListenerBufferQueue::ProxyConsumerListener在创建时又接收了ConsumerBase,所以调用到了ConsumerBaseonFrameAvailable中,ConsumerBase这里面又有一个成员变量mFrameAvailableListener,类型为BufferQueueLayer,所以最终是调用到了BufferQueueLayer的具体实现onFrameAvailable中,对这块已经绘制好的buffer进一步处理

到此生产者-消费者模型结构已经大致分析完毕,除了创建最重要的BufferQueueCoreBufferQueueProducerBufferQueueConsumer,另外就是两个重要的监听器了ConsumerListenerFrameAvailableListener,这两个监听器传过来传过去的,有点容易混乱,需要多看代码。

标签:ProxyConsumerListener,图形系统,const,生产者,sp,AndroidQ,ConsumerBase,listener,BufferQue
来源: https://blog.csdn.net/qq_34211365/article/details/106503902

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有