Android图形框架之BLASTBufferQueue 初始化

542 阅读13分钟

0 引言

在Android图形框架之SurfaceComposerClient 提交事务过程中,构建了通过SurfaceControl构建了一个事务Transaction,并将该事务提交给SurfaceFlinger进行处理。接下来我们将创建一个BLASTBufferQueue

在 Android 图形框架中,BLASTBufferQueue 是一个与 SurfaceFlinger 配合使用的组件,它处理多个图层的缓冲区交换和合成。BLASTBufferQueue 是 SurfaceFlinger 中用于实现 BufferQueue 功能的一个关键部分,它支持高效的缓冲区管理,并帮助 SurfaceFlinger 实现低延迟的图层合成和显示。

下面是本文即将分析的代码:

sp<BLASTBufferQueue> mBlastBufferQueue = new BLASTBufferQueue("DemoBLASTBufferQueue", surfaceControl ,
                                                                  resolution.getWidth(), resolution.getHeight(),
                                                                  PIXEL_FORMAT_RGBA_8888);

1 BLASTBufferQueue类

首先来看看BLASTBufferQueue类的定义:

class BLASTBufferQueue : public ConsumerBase::FrameAvailableListener {
public:
    BLASTBufferQueue(const std::string& name, const sp<SurfaceControl>& surface, int width,
                     int height, int32_t format);
    sp<IGraphicBufferProducer> getIGraphicBufferProducer() const {
        return mProducer;
    }
    sp<Surface> getSurface(bool includeSurfaceControlHandle);
    void update(const sp<SurfaceControl>& surface, uint32_t width, uint32_t height, int32_t format);
    
private:
    sp<IGraphicBufferConsumer> mConsumer;
    sp<IGraphicBufferProducer> mProducer;
    sp<BLASTBufferItemConsumer> mBufferItemConsumer;

可以看到BLASTBufferQueue是继承自FrameAvailableListener的一个类,而FrameAvailableListener 是一个接口类,定义了与缓冲区项(BufferItem)相关的回调方法。它继承自 RefBase,并包含多个纯虚函数,这些函数通常用于在消费端接收到帧或缓冲区项时进行处理。它的定义如下:

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

创建BLASTBufferQueue首先调用的是它的构造函数,如下:

BLASTBufferQueue::BLASTBufferQueue(const std::string& name, const sp<SurfaceControl>& surface,
                                   int width, int height, int32_t format)
      : BLASTBufferQueue(name) {
    update(surface, width, height, format);
}

从构造函数中可以看到,首先会调用一个重载的BLASTBufferQueue(name)构造函数,然后再调用函数update,它将根据参数surface、width、height和format来完成内部更新。首先看一下这个重载的构造函数:

2 BLASTBufferQueue(name)构造函数

BLASTBufferQueue构造函数主要完成BufferQueue的初始化,以及创建一个BLASTBufferItemConsumer,其他的则是基本参数配置。

BLASTBufferQueue::BLASTBufferQueue(const std::string& name, bool updateDestinationFrame)
      : mSurfaceControl(nullptr),
        mSize(1, 1),
        mRequestedSize(mSize),
        mFormat(PIXEL_FORMAT_RGBA_8888),
        mTransactionReadyCallback(nullptr),
        mSyncTransaction(nullptr),
        mUpdateDestinationFrame(updateDestinationFrame) {
        
    // 调用createBufferQueue创建生产者和消费者端对象
    createBufferQueue(&mProducer, &mConsumer);
    // since the adapter is in the client process, set dequeue timeout
    // explicitly so that dequeueBuffer will block
    mProducer->setDequeueTimeout(std::numeric_limits<int64_t>::max());

    // safe default, most producers are expected to override this
    mProducer->setMaxDequeuedBufferCount(2);
    mBufferItemConsumer = new BLASTBufferItemConsumer(mConsumer,
                                                      GraphicBuffer::USAGE_HW_COMPOSER |
                                                              GraphicBuffer::USAGE_HW_TEXTURE,
                                                      1, false, this);
    static std::atomic<uint32_t> nextId = 0;
    mProducerId = nextId++;
    mName = name + "#" + std::to_string(mProducerId);
    auto consumerName = mName + "(BLAST Consumer)" + std::to_string(mProducerId);
    mQueuedBufferTrace = "QueuedBuffer - " + mName + "BLAST#" + std::to_string(mProducerId);
    mBufferItemConsumer->setName(String8(consumerName.c_str()));
    mBufferItemConsumer->setFrameAvailableListener(this);

    ComposerServiceAIDL::getComposerService()->getMaxAcquiredBufferCount(&mMaxAcquiredBuffers);
    mBufferItemConsumer->setMaxAcquiredBufferCount(mMaxAcquiredBuffers);
    mCurrentMaxAcquiredBufferCount = mMaxAcquiredBuffers;
    mNumAcquired = 0;
    mNumFrameAvailable = 0;

    TransactionCompletedListener::getInstance()->addQueueStallListener(
            [&](const std::string& reason) {
                std::function<void(const std::string&)> callbackCopy;
                {
                    std::unique_lock _lock{mMutex};
                    callbackCopy = mTransactionHangCallback;
                }
                if (callbackCopy) callbackCopy(reason);
            },
            this);

    BQA_LOGV("BLASTBufferQueue created");
}

2.1 createBufferQueue函数

下面的代码比较简洁易懂,它分别new了三个对象:BufferQueueCore、BBQBufferQueueProducer和BufferQueueConsumer。

void BLASTBufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
                                         sp<IGraphicBufferConsumer>* outConsumer) {
    LOG_ALWAYS_FATAL_IF(outProducer == nullptr, "BLASTBufferQueue: outProducer must not be NULL");
    LOG_ALWAYS_FATAL_IF(outConsumer == nullptr, "BLASTBufferQueue: outConsumer must not be NULL");

    // 创建BufferQueueCore
    sp<BufferQueueCore> core(new BufferQueueCore());
    LOG_ALWAYS_FATAL_IF(core == nullptr, "BLASTBufferQueue: failed to create BufferQueueCore");

    // 创建BBQBufferQueueProducer
    sp<IGraphicBufferProducer> producer(new BBQBufferQueueProducer(core, this));
    LOG_ALWAYS_FATAL_IF(producer == nullptr,
                        "BLASTBufferQueue: failed to create BBQBufferQueueProducer");

    // 创建BufferQueueConsumer
    sp<BufferQueueConsumer> consumer(new BufferQueueConsumer(core));
    consumer->setAllowExtraAcquire(true);
    LOG_ALWAYS_FATAL_IF(consumer == nullptr,
                        "BLASTBufferQueue: failed to create BufferQueueConsumer");

    *outProducer = producer;
    *outConsumer = consumer;
}

2.1.1 创建 BufferQueueCore

BufferQueueCore::BufferQueueCoreBufferQueue 核心部分的构造函数,它初始化了内部数据结构和状态变量。这些变量用于管理缓冲区的分配、释放、排队、消费等操作。

BufferQueueCore::BufferQueueCore()
      : mMutex(),
        mIsAbandoned(false),
        mConsumerControlledByApp(false),
        mConsumerName(getUniqueName()),
        mConsumerListener(),
        mConsumerUsageBits(0),
        mConsumerIsProtected(false),
        mConnectedApi(NO_CONNECTED_API),
        mLinkedToDeath(),
        mConnectedProducerListener(),
        mBufferReleasedCbEnabled(false),
        mSlots(),
        mQueue(),
        mFreeSlots(),
        mFreeBuffers(),
        mUnusedSlots(),
        mActiveBuffers(),
        mDequeueCondition(),
        mDequeueBufferCannotBlock(false),
        mQueueBufferCanDrop(false),
        mLegacyBufferDrop(true),
        mDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888),
        mDefaultWidth(1),
        mDefaultHeight(1),
        mDefaultBufferDataSpace(HAL_DATASPACE_UNKNOWN),
        mMaxBufferCount(BufferQueueDefs::NUM_BUFFER_SLOTS),
        mMaxAcquiredBufferCount(1),
        mMaxDequeuedBufferCount(1),
        mBufferHasBeenQueued(false),
        mFrameCounter(0),
        mTransformHint(0),
        mIsAllocating(false),
        mIsAllocatingCondition(),
        mAllowAllocation(true),
        mBufferAge(0),
        mGenerationNumber(0),
        mAsyncMode(false),
        mSharedBufferMode(false),
        mAutoRefresh(false),
        mSharedBufferSlot(INVALID_BUFFER_SLOT),
        mSharedBufferCache(Rect::INVALID_RECT, 0, NATIVE_WINDOW_SCALING_MODE_FREEZE,
                           HAL_DATASPACE_UNKNOWN),
        mLastQueuedSlot(INVALID_BUFFER_SLOT),
        mUniqueId(getUniqueId()),
        mAutoPrerotation(false),
        mTransformHintInUse(0) {
    int numStartingBuffers = getMaxBufferCountLocked();
    for (int s = 0; s < numStartingBuffers; s++) {
        mFreeSlots.insert(s);
    }
    for (int s = numStartingBuffers; s < BufferQueueDefs::NUM_BUFFER_SLOTS;
            s++) {
        mUnusedSlots.push_front(s);
    }
}

上面的构造函数太多初始化变量了,我们找到最关键的几个:

BufferQueueDefs::SlotsType mSlots;  // 等同于 BufferSlot[64] mSlots
Fifo mQueue; // 等同于 Vector<BufferItem> mQueue
std::set<int> mFreeSlots;
std::list<int> mFreeBuffers;
std::list<int> mUnusedSlots;
std::set<int> mActiveBuffers;

SlotsType的原类型为BufferSlot[NUM_BUFFER_SLOTS](64),因此mSlots为大小为64的BufferSlot类型数组Fifo的原类型为Vector<BufferItem>因此mQueue为存放BufferItem的数组

因此我们先去看一下BufferSlot类是什么:

struct BufferSlot {

    BufferSlot()
    : mGraphicBuffer(nullptr),
      mEglDisplay(EGL_NO_DISPLAY),
      mBufferState(),
      mRequestBufferCalled(false),
      mFrameNumber(0),
      mEglFence(EGL_NO_SYNC_KHR),
      mFence(Fence::NO_FENCE),
      mAcquireCalled(false),
      mNeedsReallocation(false) {
    }

    // mGraphicBuffer指向一个GraphicBuffer
    sp<GraphicBuffer> mGraphicBuffer;

    // mEglDisplay is the EGLDisplay used to create EGLSyncKHR objects.
    EGLDisplay mEglDisplay;

    // 定义buffer slot的当前状态,有五种状态:.FREE DEQUEUED QUEUED ACQUIRED SHARED
    BufferState mBufferState;

    // 用于调试,确保生产者调用了 requestBuffer()
    bool mRequestBufferCalled;

    // 该slot对应帧队列的帧编号
    uint64_t mFrameNumber;

    // 已废弃,被mFence替代
    EGLSyncKHR mEglFence;

    // 用于指示生产者是否完成了对buffer的写操作,或者消费者是否完成对buffer的读操作
    sp<Fence> mFence;

    // 用于指示该buffer是否已被消费者获取
    bool mAcquireCalled;

    // 指示该buffer是否需要在没有通知生产者的情况下被重新分配,如果是,则在出队时需要标记为true。
    bool mNeedsReallocation;
};

从代码和注释中可以看到,这里主要是定义了buffer的状态和行为模式。我们深入看一下BufferState这个类:

struct BufferState {

    // All slots are initially FREE (not dequeued, queued, acquired, or shared).
    BufferState()
    : mDequeueCount(0),
      mQueueCount(0),
      mAcquireCount(0),
      mShared(false) {
    }

    uint32_t mDequeueCount;
    uint32_t mQueueCount;
    uint32_t mAcquireCount;
    bool mShared;

    inline bool isFree() const {
        return !isAcquired() && !isDequeued() && !isQueued();
    }

    inline bool isDequeued() const {
        return mDequeueCount > 0;
    }

    inline bool isQueued() const {
        return mQueueCount > 0;
    }

    inline bool isAcquired() const {
        return mAcquireCount > 0;
    }

    inline bool isShared() const {
        return mShared;
    }

    inline void reset() {
        *this = BufferState();
    }

    const char* string() const;

    inline void dequeue() {
        mDequeueCount++;
    }

    inline void detachProducer() {
        if (mDequeueCount > 0) {
            mDequeueCount--;
        }
    }

    inline void attachProducer() {
        mDequeueCount++;
    }

    inline void queue() {
        if (mDequeueCount > 0) {
            mDequeueCount--;
        }
        mQueueCount++;
    }

    inline void cancel() {
        if (mDequeueCount > 0) {
            mDequeueCount--;
        }
    }

    inline void freeQueued() {
        if (mQueueCount > 0) {
            mQueueCount--;
        }
    }

    inline void acquire() {
        if (mQueueCount > 0) {
            mQueueCount--;
        }
        mAcquireCount++;
    }

    inline void acquireNotInQueue() {
        mAcquireCount++;
    }

    inline void release() {
        if (mAcquireCount > 0) {
            mAcquireCount--;
        }
    }

    inline void detachConsumer() {
        if (mAcquireCount > 0) {
            mAcquireCount--;
        }
    }

    inline void attachConsumer() {
        mAcquireCount++;
    }
};

BufferState定义了五个状态,它们可以用下面这张表表示:

        | 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.png

大致解释一下这个状态机:通常情况下,初始buffer的状态为FREE,当对它执行dequeue操作后,它会进入DEQUEUED状态,此时Producer可以对buffer进行写入操作。Producer写完数据后,对该buffer执行queue操作,进入QUEUED状态。这个时候如果有Consumer想要读取该buffer的数据,可以对其进行acquire操作,此时buffer进入ACQUIRED状态。当Consumer读取完数据后,可以进行release操作,将buffer重新变为FREE状态。

当然buffer还有一些其他的操作,这里不详细讨论。

下面讲一下Fifo mQueue,即Fifo其实是Vector<BufferItem> 的别名。看一下BufferItem的定义:

class BufferItem : public Flattenable<BufferItem> {
    friend class Flattenable<BufferItem>;
    size_t getPodSize() const;
    size_t getFlattenedSize() const;
    size_t getFdCount() const;
    status_t flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const;
    status_t unflatten(void const*& buffer, size_t& size, int const*& fds, size_t& count);

    public:
    // The default value of mBuf, used to indicate this doesn't correspond to a slot.
    enum { INVALID_BUFFER_SLOT = -1 };
    BufferItem();
    ~BufferItem();
    BufferItem(const BufferItem&) = default;
    BufferItem& operator=(const BufferItem&) = default;

    static const char* scalingModeName(uint32_t scalingMode);

    // 指向一个GraphicBuffer,和BufferSlot一样
    sp<GraphicBuffer> mGraphicBuffer;

    // 用于指示buffer何时处于空闲状态
    sp<Fence> mFence;

    // 用于表示buffer的时间戳
    std::shared_ptr<FenceTime> mFenceTime{FenceTime::NO_FENCE};

    // 用于表示buffer的裁剪矩形区域
    Rect mCrop;

    // 用于表示buffer的变换标志(旋转、镜像)
    uint32_t mTransform;

    // 用于表示buffer的缩放模式
    uint32_t mScalingMode;

    // 表示buffer的时间戳
    int64_t mTimestamp;

    // 指示时间戳是否由系统自动生成
    bool mIsAutoTimestamp;

    // 表示buffer的色彩空间
    android_dataspace mDataSpace;

    // 表示buffer的HDR元数据
    HdrMetadata mHdrMetadata;

    // buffer所属帧的编号
    uint64_t mFrameNumber;

    // buffer所在slot的索引
    int mSlot;

    // 该buffer是否可丢弃
    bool mIsDroppable;

    // 该buffer是否已被消费者获取
    bool mAcquireCalled;

    // 指示是否应将buffer逆转以适应显示屏
    bool mTransformToDisplayInverse;

    // 描述自上一帧以来已修改的surface区域。
    Region mSurfaceDamage;

    // 指示消费者是否应尽早获取下一帧,不等待缓冲区变得可用,仅在共享缓冲区模式下有效。
    bool mAutoRefresh;

    // 指示该缓冲区是否已由生产者排队
    bool mQueuedBuffer;

    // 指示该缓冲区是否已经被release
    bool mIsStale;

    // 指示buffer的API类型
    int mApi;
};

可以看到BufferItem 和 BufferSlot 比较类似,尤其是它们内部都有一个智能指针sp<GraphicBuffer> mGraphicBuffer,可以指向一个GraphicBuffer。而slot也是通过它来进行区分,例如:mFreeSlot指的是mGraphicBuffer为null且BufferState为FREE的BufferSlot;mFreeBuffers指的是mGraphicBuffer不为null 但BufferState为FREE的BufferSlot;mUnusedSlots指的是尚未参与使用的BufferSlot;mActiveBuffers指的是mGraphicBuffer不为null且BufferState不为FREE的BufferSlot。

根据上面的分析总结成下面这张表格:

成员变量含义
mSlotsSlotsType的原类型为BufferSlot[NUM_BUFFER_SLOTS](64),因此mSlots为大小为64的BufferSlot类型数组
mQueueFifo的原类型为Vector<BufferItem>因此mQueue为存放BufferItem的数组
mFreeSlotsmFreeSlot指的是mGraphicBuffer为null且BufferState为FREE的BufferSlot
mFreeBuffersmFreeBuffers指的是mGraphicBuffer不为null但BufferState为FREE的BufferSlot
mUnusedSlotsmUnusedSlots指的是尚未参与使用的BufferSlot
mActiveBuffersmActiveBuffers指的是mGraphicBuffer不为null且BufferState不为FREE的BufferSlot

2.1.2 创建 BBQBufferQueueProducer

BBQBufferQueueProducer顾名思义是buffer的消费者,它的构造函数如下:

BBQBufferQueueProducer(const sp<BufferQueueCore>& core, wp<BLASTBufferQueue> bbq)
    : BufferQueueProducer(core, false /* consumerIsSurfaceFlinger*/),
    mBLASTBufferQueue(std::move(bbq)) {}

BufferQueueProducer::BufferQueueProducer(const sp<BufferQueueCore>& core,
        bool consumerIsSurfaceFlinger) :
    mCore(core),
    mSlots(core->mSlots),
    mConsumerName(),
    mStickyTransform(0),
    mConsumerIsSurfaceFlinger(consumerIsSurfaceFlinger),
    mLastQueueBufferFence(Fence::NO_FENCE),
    mLastQueuedTransform(0),
    mCallbackMutex(),
    mNextCallbackTicket(0),
    mCurrentCallbackTicket(0),
    mCallbackCondition(),
    mDequeueTimeout(-1),
    mDequeueWaitingForAllocation(false) {}

从上述代码可以看出,BBQBufferQueueProducer主要通过前面创建的BufferQueueCore类对应的实例core来初始化变量mCore和mSlots。我们再来看看BBQBufferQueueProducer 类的定义,它是继承并扩展 BufferQueueProducer 的一个类。

#ifndef NO_BINDER
class BufferQueueProducer : public BnGraphicBufferProducer,
                            private IBinder::DeathRecipient {
#else
class BufferQueueProducer : public BnGraphicBufferProducer {
#endif
public:
    friend class BufferQueue; 

    explicit BufferQueueProducer(const sp<BufferQueueCore>& core,
                                 bool consumerIsSurfaceFlinger = false);
    ~BufferQueueProducer() override;

    // 从某个slot中请求一个buffer
    virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf);

    // 设置最大可出队缓冲区的数量
    virtual status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers);

    // 设置队列是否工作在异步模式
    virtual status_t setAsyncMode(bool async);

    // 从某个slot中分离一个buffer
    virtual status_t detachBuffer(int slot);

    virtual status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer,
            sp<Fence>* outFence);

    // 从某个slot中加入一个buffer
    virtual status_t attachBuffer(int* outSlot, const sp<GraphicBuffer>& buffer);

    // 将某个slot中的buffer加入到队列中
    virtual status_t queueBuffer(int slot,
            const QueueBufferInput& input, QueueBufferOutput* output);
    
    // 取消对一个buffer的操作
    virtual status_t cancelBuffer(int slot, const sp<Fence>& fence);

    // 将生产者连接到 BufferQueue
    virtual status_t connect(const sp<IProducerListener>& listener,
            int api, bool producerControlledByApp, QueueBufferOutput* output);

    // 断开生产者与 BufferQueue的连接
    virtual status_t disconnect(int api, DisconnectMode mode = DisconnectMode::Api);

    virtual String8 getConsumerName() const override;

    // 设置共享缓冲区模式
    virtual status_t setSharedBufferMode(bool sharedBufferMode) override;

    // 设置自动刷新
    virtual status_t setAutoRefresh(bool autoRefresh) override;

protected:
    status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers, int* maxBufferCount);

private:
    sp<BufferQueueCore> mCore;
    
    BufferQueueDefs::SlotsType& mSlots;

    String8 mConsumerName;
};

从上面的代码中可以看到BufferQueueProducer类定义了许多虚函数,例如requestBuffer、detachBuffer、attachBuffer和queueBuffer等等。这些接口用于对slot中的buffer进行各种操作。

2.1.3 创建 BufferQueueConsumer

BufferQueueConsumer顾名思义是buffer的消费者,它继承自BnGraphicBufferConsumer类,它的构造函数更加简单一些:

BufferQueueConsumer::BufferQueueConsumer(const sp<BufferQueueCore>& core) :
    mCore(core),
    mSlots(core->mSlots),
    mConsumerName() {}

我们再来看看BufferQueueConsumer类的定义:

class BufferQueueConsumer : public BnGraphicBufferConsumer {

public:
    explicit BufferQueueConsumer(const sp<BufferQueueCore>& core);
    ~BufferQueueConsumer() override;

    // 请求一个BufferItem
    virtual status_t acquireBuffer(BufferItem* outBuffer,
            nsecs_t expectedPresent, uint64_t maxFrameNumber = 0) override;

    // 将某个slot从队列中分离
    virtual status_t detachBuffer(int slot);

    // 将buffer添加到某个槽中
    virtual status_t attachBuffer(int* slot, const sp<GraphicBuffer>& buffer);

    // 释放某个slot,以便生产者可以重新使用
    virtual status_t releaseBuffer(int slot, uint64_t frameNumber,
            const sp<Fence>& releaseFence, EGLDisplay display,
            EGLSyncKHR fence);

    // 连接消费者到BufferQueue,使其能够获取缓冲区。
    virtual status_t connect(const sp<IConsumerListener>& consumerListener,
            bool controlledByApp);

    // 断开消费者与BufferQueue的连接
    virtual status_t disconnect();

    // 获取已经被释放但尚未重新分配的slot的掩码
    virtual status_t getReleasedBuffers(uint64_t* outSlotMask);

    // 设置buffer的默认尺寸
    virtual status_t setDefaultBufferSize(uint32_t width, uint32_t height);

    // 调整BufferQueue的容量
    virtual status_t setMaxBufferCount(int bufferCount);

    // 设置消费者可以同时获取的最大buffer数量
    virtual status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers);

    status_t setConsumerName(const String8& name) override;

    // 连接消费者和BufferQueue
    virtual status_t consumerConnect(const sp<IConsumerListener>& consumer,
            bool controlledByApp) {
        return connect(consumer, controlledByApp);
    }

    // 断开消费者和BufferQueue的连接
    virtual status_t consumerDisconnect() { return disconnect(); }

private:
    sp<BufferQueueCore> mCore;

    // This references mCore->mSlots. Lock mCore->mMutex while accessing.
    BufferQueueDefs::SlotsType& mSlots;

    String8 mConsumerName;

};

BufferQueueConsumer 提供了消费者端缓冲区管理的完整功能:

  • 缓冲区获取与释放acquireBufferreleaseBufferdetachBufferattachBuffer
  • 队列配置与控制setMaxBufferCountsetDefaultBufferSize
  • 连接与状态管理consumerConnectconsumerDisconnect

与生产者类似,消费者通过这些接口高效管理缓冲区,确保图形系统中的帧数据流畅传递。

2.2 new BLASTBufferItemConsumer

当BufferQueueCoreBBQBufferQueueProducerBufferQueueConsumer都创建好后,createBufferQueue函数也就执行完毕了。让我们回到BLASTBufferQueue的构造函数中,继续往下看非常重要的内容就是BLASTBufferItemConsumer的初始化了:

mBufferItemConsumer = new BLASTBufferItemConsumer(mConsumer,
                                                  GraphicBuffer::USAGE_HW_COMPOSER |
                                                  GraphicBuffer::USAGE_HW_TEXTURE,
                                                  1, false, this);

BLASTBufferItemConsumer的构造函数如下:

BLASTBufferItemConsumer(const sp<IGraphicBufferConsumer>& consumer, uint64_t consumerUsage,
                        int bufferCount, bool controlledByApp, wp<BLASTBufferQueue> bbq)
      : BufferItemConsumer(consumer, consumerUsage, bufferCount, controlledByApp),
        mBLASTBufferQueue(std::move(bbq)),
        mCurrentlyConnected(false),
        mPreviouslyConnected(false) {}

BLASTBufferItemConsumer继承自BufferItemConsumer,因此它的构造函数实际上就是对BufferItemConsumer的构造,以及初始化mBLASTBufferQueue。接下来将重点分析BufferItemConsumer类。

BufferItemConsumer的类定义代码如下:

class BufferItemConsumer: public ConsumerBase
{
  public:
    typedef ConsumerBase::FrameAvailableListener FrameAvailableListener;

    // 定义了一个监听接口:用于监听buffer状态变为FREE的情况
    struct BufferFreedListener : public virtual RefBase {
        virtual void onBufferFreed(const wp<GraphicBuffer>& graphicBuffer) = 0;
    };

    enum { DEFAULT_MAX_BUFFERS = -1 }; // 默认最大buffer数量
    enum { INVALID_BUFFER_SLOT = BufferQueue::INVALID_BUFFER_SLOT };
    enum { NO_BUFFER_AVAILABLE = BufferQueue::NO_BUFFER_AVAILABLE };

    BufferItemConsumer(const sp<IGraphicBufferConsumer>& consumer,
            uint64_t consumerUsage, int bufferCount = DEFAULT_MAX_BUFFERS,
            bool controlledByApp = false);

    ~BufferItemConsumer() override;

    // 设置buffer空闲监听器
    void setBufferFreedListener(const wp<BufferFreedListener>& listener);

    // 获取一个可用的BufferItem
    status_t acquireBuffer(BufferItem* item, nsecs_t presentWhen,
            bool waitForFence = true);

    // 释放当前的BufferItem
    status_t releaseBuffer(const BufferItem &item,
            const sp<Fence>& releaseFence = Fence::NO_FENCE);

   private:
    void freeBufferLocked(int slotIndex) override;
    wp<BufferFreedListener> mBufferFreedListener;
};

从上面的代码中可以知道BufferItemConsumer可以获取BufferItem然后进行使用,它是BLASTBufferQueue的消费者。

3 update函数

void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, uint32_t width, uint32_t height,
                              int32_t format) {
    LOG_ALWAYS_FATAL_IF(surface == nullptr, "BLASTBufferQueue: mSurfaceControl must not be NULL");

    std::lock_guard _lock{mMutex};
    
    // 更新格式
    if (mFormat != format) {
        mFormat = format;
        mBufferItemConsumer->setDefaultBufferFormat(convertBufferFormat(format));
    }

    // 判断SurfaceControl是否发生变化
    const bool surfaceControlChanged = !SurfaceControl::isSameSurface(mSurfaceControl, surface);
    if (surfaceControlChanged && mSurfaceControl != nullptr) {
        BQA_LOGD("Updating SurfaceControl without recreating BBQ");
    }
    bool applyTransaction = false;

    // 更新当前SurfaceControl
    mSurfaceControl = surface;
    
    // 创建新的事务,如果SurfaceControl发生变化则将准备应用新的事务
    SurfaceComposerClient::Transaction t;
    if (surfaceControlChanged) {
        t.setFlags(mSurfaceControl, layer_state_t::eEnableBackpressure,
                   layer_state_t::eEnableBackpressure);
        applyTransaction = true;
    }
    
    // 设置变化提示并打印信息
    mTransformHint = mSurfaceControl->getTransformHint();
    mBufferItemConsumer->setTransformHint(mTransformHint);
    BQA_LOGV("update width=%d height=%d format=%d mTransformHint=%d", width, height, format,
             mTransformHint);

    // 构造新的ui::size,如果和之前的不同则进行更新
    ui::Size newSize(width, height);
    if (mRequestedSize != newSize) {
        mRequestedSize.set(newSize);
        // 设置新的缓冲区size
        mBufferItemConsumer->setDefaultBufferSize(mRequestedSize.width, mRequestedSize.height);
        
        // 如果缓冲区的缩放模式不是冻结(`NATIVE_WINDOW_SCALING_MODE_FREEZE`)
        // 并且设置了 `mUpdateDestinationFrame`
        // 则更新 `SurfaceControl` 的目标帧(`setDestinationFrame`)以反映新的尺寸。
        if (mLastBufferInfo.scalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE) {
            mSize = mRequestedSize;
            if (mUpdateDestinationFrame) {
                t.setDestinationFrame(mSurfaceControl, Rect(newSize));
                applyTransaction = true;
            }
        }
    }
    
    // 如果需要提交新的事务
    if (applyTransaction) {
        // All transactions on our apply token are one-way. See comment on mAppliedLastTransaction
        t.setApplyToken(mApplyToken).apply(false, true);
    }
}

BLASTBufferQueue::update 方法的作用是更新 BLASTBufferQueue 的各种属性,包括 SurfaceControl、尺寸、格式、变换提示等。如果发生了变化,它会创建并应用一个事务,确保图形系统的状态与新的参数一致。通过使用事务,能够确保图形操作的原子性,并在多线程环境中安全地进行图形更新。