SurfaceFlinger BlastBufferQueue生产者消费者模型(4)

SurfaceFlinger BlastBufferQueue生产者消费者模型

简述

BlastBufferQueue是一个消费者生产者的模型,他们消费生产的对象是GraphicBuffer,GraphicBuffer其实就是一块内存,只不过是一块比较特殊的内存,使用的是dma buffer,相比于一般的内存,它是一块更高效的跨进程共享内存,后面会专门有一篇来介绍它。
在Android 12开始,无论是这个模型的消费者还是生产者都在app侧,应用在渲染前,去队列里拿一块buffer,然后进行渲染,后放回队列,并且通知消费者可以取buffer消费,就是让SurfaceFlinger用于合成。
在开始介绍BlastBufferQueue之前,我们还有要介绍一下fence,栅栏。大家在多线程编程中都接触过锁吧,用来保证多线程读写数据时候的线程安全,fence其实也是类似,只不过fence可以跨越进程和硬件设备。(在我们现在这个场景设备说的是cpu,gpu,hwc)

Fence 栅栏

我们上一片详细说过fence的,这里只再简单复述一下他的作用,因为在这篇文章中会经常看到。
fence的作用和多线程中的锁类似,只不过他是跨进程,跨硬件的。我们这里生产者需要gpu来渲染,消费者拿到buffer可能需要hwc来合成,所以需要跨设备。
举个我们本节内容的具体的例子:
我们Surface.lock后会获取一个buffer,然后要通过cpu执行一些opengel指令告诉gpu怎么渲染,cpu执行完后,gpu不可能立刻完成渲染。这时候cpu有两种方案,一个是等gpu执行完,然后再把这个buffer给出去,但是这样会浪费这个cpu的资源;第二种方案,就是通过fence,cpu可以继续执行其他任务,到需要使用这个buffer的时候,再通过fence来确认gpu任务是否完成。

BlastBufferQueue构建

1.1 updateBlastSurfaceIfNeeded()
我们在SurfaceFlinger和端侧的Binder框架文章的末尾提到了WMS将构建好的SurfaceContorl传回app后,app会构建BlastBufferQueue。

void updateBlastSurfaceIfNeeded() {
    if (!mSurfaceControl.isValid()) {
        return;
    }

    if (mBlastBufferQueue != null && mBlastBufferQueue.isSameSurfaceControl(mSurfaceControl)) {
        mBlastBufferQueue.update(mSurfaceControl,
            mSurfaceSize.x, mSurfaceSize.y,
            mWindowAttributes.format);
        return;
    }

    if (mBlastBufferQueue != null) {
        mBlastBufferQueue.destroy();
    }
    // 首次走这里,构建消费者生产者队列模型。详见1.2
    mBlastBufferQueue = new BLASTBufferQueue(mTag, mSurfaceControl,
            mSurfaceSize.x, mSurfaceSize.y, mWindowAttributes.format);
    mBlastBufferQueue.setTransactionHangCallback(sTransactionHangCallback);
    // 构建Sufrace。
    Surface blastSurface = mBlastBufferQueue.createSurface();
    mSurface.transferFrom(blastSurface);
}

1.2 BLASTBufferQueue构造函数
调用了nativeCreate构造c++层的BlastBufferQueue,并且返回c++侧这个对象的内存地址,记录到mNativeObject进行关联。
调用nativeUpdate更新参数。它不仅会修改app层buffer的参数,还会通知到SurfaceFlinger。
这个模式和上一篇文章介绍的SurfaceControl类似,java层和c++层各有一个对象相互关联起来,这个用法非常常见。

public BLASTBufferQueue(String name, SurfaceControl sc, int width, int height,
        @PixelFormat.Format int format) {
    // 调用重载的构造方法,后面会调用nativeCreate
    this(name, true /* updateDestinationFrame */);
    // 更新参数,实际会调用到native方法
    update(sc, width, height, format);
}

public BLASTBufferQueue(String name, boolean updateDestinationFrame) {
    // 调用nativeCreate构造c++侧的BLASTBufferQueue,返回一个地址
    // 详见1.3
    mNativeObject = nativeCreate(name, updateDestinationFrame);
}

public void update(SurfaceControl sc, int width, int height, @PixelFormat.Format int format) {
    nativeUpdate(mNativeObject, sc.mNativeObject, width, height, format);
}

1.3 BLASTBufferQueue::nativeCreate
构造BLASTBufferQueue

static jlong nativeCreate(JNIEnv* env, jclass clazz, jstring jName,
                      jboolean updateDestinationFrame) {
    ScopedUtfChars name(env, jName);
    // 构造c++的BLASTBufferQueue,详见1.4
    sp<BLASTBufferQueue> queue = new BLASTBufferQueue(name.c_str(), updateDestinationFrame);
    queue->incStrong((void*)nativeCreate);
    return reinterpret_cast<jlong>(queue.get());
}

1.4 BLASTBufferQueue构造函数(c++侧)
初始化一些变量
调用了createBufferQueue创建生产者和消费者
createBufferQueue里面构造的消费者是BufferQueueConsumer,然后这里通过它构造BLASTBufferItemConsumer。
同时还配置了消费者和生产者的一些参数,超时以及存取最大Buffer。
调用setFrameAvailableListener注册了回调。

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) {
// 构造队列,详见1.5
createBufferQueue(&mProducer, &mConsumer);
mProducer->setDequeueTimeout(std::numeric_limits<int64_t>::max());

mProducer->setMaxDequeuedBufferCount(2);
// mConsumer指向createBufferQueue里面构造的BufferQueueConsumer
// BLASTBufferItemConsumer这里就是包装了一下BufferQueueConsumer,详见1.8
mBufferItemConsumer = new BLASTBufferItemConsumer(mConsumer,
                            GraphicBuffer::USAGE_HW_COMPOSER |
                            GraphicBuffer::USAGE_HW_TEXTURE,
                            1, false, this);
    static std::atomic<uint32_t> nextId = 0;
    mProducerId = nextId++;
    // 这里注册了listener回调,this就是BLASTBufferQueue,细节1.9会介绍
    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");
}

1.5 createBufferQueue

void BLASTBufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
                                     sp<IGraphicBufferConsumer>* outConsumer) {
    // 。。。
    // 构造队列,详见1.5.1
    sp<BufferQueueCore> core(new BufferQueueCore());
    // 。。。
    // 构造生产者,详见 1.6
    sp<IGraphicBufferProducer> producer(new BBQBufferQueueProducer(core, this));
    // 构造消费者,详见 1.7
    sp<BufferQueueConsumer> consumer(new BufferQueueConsumer(core));
    consumer->setAllowExtraAcquire(true);
    *outProducer = producer;
    *outConsumer = consumer;
}

1.5.1 BufferQueueCore构造函数
BufferQueueCore是这个消费者生产者模型记录数据的类,可以看到这里初始化了大量的变量。我们来介绍一些比较核心的变量。

  • mSlots,SlotsType类型
    typedef BufferSlot SlotsType[NUM_BUFFER_SLOTS]
    NUM_BUFFER_SLOTS是64,mSlots就是一个BufferSlot的数组,BufferSlot里面有一个GraphicBuffer的指针,记录了关联的buffer,还有一个Fence指针和EGLSyncKHR,分别用于渲染和合成的同步。
    Slots可以理解为一个缓存池,避免重复构造释放对象。
  • mQueue,Fifo类型
    typedef Vector Fifo
    这个是消费者生产者队列,BufferItem里面有一个对应mSlot的索引,还有一个Fence指针,一个GraphicBuffer指针。
  • mFreeSlots set
    mSlots空闲的索引。这里的空闲是指没有关联buffer,即GraphicBuffer的指针为空
  • mFreeBuffer list
    mSlot空闲的索引。这些BufferSlot是已经关联GraphicBuffer的。
  • mUnusedSlots list
    从未使用过的mSlot索引,前面我们说过mSlot是大小为64的数组,但是一般并不会64个都用到,BufferQueueCore有一个变量mMaxBufferCount来决定会有多少个Slot会被用到。
  • mActiveBuffers std::set
    包含所有non-free状态buffer的Slot,DEQUEUED,QUEUED,ACQUIRED以及SHARED
  • mAllowAllocation bool
    决定dequeueBuffer过程中是否允许去分配GraphicBuffer

这里Slot有5种状态,DEQUEUED,QUEUED,ACQUIRED,FREE,SHARED
这几种状态逻辑很简单
生产者调用dequeueBuffer获取slot后就进入DEQUEUED状态
生产者使用完buffer调用queueBuffer后把buffer放到列表里就进入了QUEUED状态
消费者使用acquireBuffer获取Buffer后buffer就进入ACQUIRED状态
消费者使用releaseBuffer把Buffer释放后,就进入FREE状态
SHARED状态比较特殊,这里有一个共享Buffer模式,看代码实现逻辑就是一直共享复用一个buffer,这种情况这个buffer就是SHARED状态,默认情况是不使用这种模式的,我们不会太关注这个。

其实光看这些变量我们就大概能猜到这个BlastBufferQueue大体是怎么运作的了。

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

1.6 BBQBufferQueueProducer继承BufferQueueProducer
BBQBufferQueueProducer把BLASTBufferQueue存在了变量里,然后调用父类的构造函数。
BufferQueueProducer构造函数初始化了一些变量,主要注意的是mCore和mSlots,存了前面构造的BufferQueueCore以及mSlots

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) {}

1.7 BufferQueueConsumer构造函数也很简单,主要也是存了一下BufferQueueCore以及mSlots

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

1.8 BLASTBufferItemConsumer构造函数
这里主要有consumerlistener的注册,生产者queueBuffer后就会通过这个监听器来通知消费者。
继承BLASTBufferItemConsumer,会调用BufferItemConsumer的构造函数。
BufferItemConsumer继承了ConsumerBase,在ConsumerBase构造函数中调用consumerConnect进行监听器注册。

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

BufferItemConsumer::BufferItemConsumer(
    const sp<IGraphicBufferConsumer>& consumer, uint64_t consumerUsage,
    int bufferCount, bool controlledByApp) :
    ConsumerBase(consumer, controlledByApp)
{
    status_t err = mConsumer->setConsumerUsageBits(consumerUsage);
    LOG_ALWAYS_FATAL_IF(err != OK,
            "Failed to set consumer usage bits to %#" PRIx64, consumerUsage);
    if (bufferCount != DEFAULT_MAX_BUFFERS) {
        err = mConsumer->setMaxAcquiredBufferCount(bufferCount);
        LOG_ALWAYS_FATAL_IF(err != OK,
                "Failed to set max acquired buffer count to %d", bufferCount);
    }
}

ConsumerBase::ConsumerBase(const sp<IGraphicBufferConsumer>& bufferQueue, bool controlledByApp) :
        mAbandoned(false),
        mConsumer(bufferQueue),
        mPrevFinalReleaseFence(Fence::NO_FENCE) {
    // Choose a name using the PID and a process-unique ID.
    mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
    // 这里的this是ConsumerBase,Consumer的回调只是做一层中转,详见1.9
    wp<ConsumerListener> listener = static_cast<ConsumerListener*>(this);
    sp<IConsumerListener> proxy = new BufferQueue::ProxyConsumerListener(listener);
    // 注册ConsumerListener
    status_t err = mConsumer->consumerConnect(proxy, controlledByApp);
    // 。。。
}

1.9 ConsumerBase::onFrameAvailable
onFrameAvailable是ConsumerListener接口的方法之一,我们就用它举例,其他的也是一样的逻辑
前面说过这里只是一层中转,最终调用的是mFrameAvailableListener变量的回调方法。
这里mFrameAvailableListener是在1.4注册的,就是BLASTBufferQueue。
后面的逻辑是消费者相关的逻辑,我们在3.1再介绍。

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

队列的生产端

我们从ViewRootImpl里面的drawSoftware开始分析数据的生产者,至于什么时候会走到这里,我们会在讲Vsync的篇章里面介绍。

做过app开发一定知道,写自定义view的时候我们会复写onDraw去实现想要的效果,而onDraw就是在这里调用的。
现在版本的android基本已经不用软件渲染了,都是硬件渲染,但是我们还是都介绍了一下他们的流程,不关心的软件渲染的可以直接跳到硬件渲染

软件渲染

如果是软件绘制的话,我们就需要通过lockCanvas去取一块图元buffer,draw结束后通过unlockCanvasAndPost把buffer放回队列,供消费者使用。
在这里插入图片描述

2.1.1 ViewRootImpl.drawSoftware

private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int xoff, int yoff,
        boolean scalingRequired, Rect dirty, Rect surfaceInsets) {
    // 。。。
    // 获取图元buffer,dequeueBuffer流程,详见2.1.2
    canvas = mSurface.lockCanvas(dirty);
    // 。。。
    mView.draw(canvas);
    // 。。。
    surface.unlockCanvasAndPost(canvas);
}

2.1.2 Surface.lockCanvas
调用nativeLockCanvas

public Canvas lockCanvas(Rect inOutDirty)
        throws Surface.OutOfResourcesException, IllegalArgumentException {
    synchronized (mLock) {
        // 。。。判断是否重复锁
        // 调用nativeLockCanvas,详见2.1.3
        mLockedObject = nativeLockCanvas(mNativeObject, mCanvas, inOutDirty);
        return mCanvas;
    }
}

2.1.3 Surface::nativeLockCanvas
校验Surface,设置纹理格式
调用surface::lock进一步dequeueBuffer
配置canvas返回给java层绘制使用

static jlong nativeLockCanvas(JNIEnv* env, jclass clazz,
    jlong nativeObject, jobject canvasObj, jobject dirtyRectObj) {
    // 。。。Surface有效性校验,设置纹理格式

    Rect dirtyRect(Rect::EMPTY_RECT);
    Rect* dirtyRectPtr = NULL;
    // 获取参数里传入的脏区数据
    if (dirtyRectObj) {
        dirtyRect.left   = env->GetIntField(dirtyRectObj, gRectClassInfo.left);
        dirtyRect.top    = env->GetIntField(dirtyRectObj, gRectClassInfo.top);
        dirtyRect.right  = env->GetIntField(dirtyRectObj, gRectClassInfo.right);
        dirtyRect.bottom = env->GetIntField(dirtyRectObj, gRectClassInfo.bottom);
        dirtyRectPtr = &dirtyRect;
    }

    ANativeWindow_Buffer buffer;
    // 这里去队列中取buffer,会存到buffer里,详见2.1.4
    status_t err = surface->lock(&buffer, dirtyRectPtr);
    // 。。。 返回值检测,如果有异常则抛出一个java异常
    // 把canvas和获取的Buffer关联。
    graphics::Canvas canvas(env, canvasObj);
    canvas.setBuffer(&buffer, static_cast<int32_t>(surface->getBuffersDataSpace()));

    if (dirtyRectPtr) {
        canvas.clipRect({dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom});
    }

    if (dirtyRectObj) {
        env->SetIntField(dirtyRectObj, gRectClassInfo.left,   dirtyRect.left);
        env->SetIntField(dirtyRectObj, gRectClassInfo.top,    dirtyRect.top);
        env->SetIntField(dirtyRectObj, gRectClassInfo.right,  dirtyRect.right);
        env->SetIntField(dirtyRectObj, gRectClassInfo.bottom, dirtyRect.bottom);
    }

    sp<Surface> lockedSurface(surface);
    lockedSurface->incStrong(&sRefBaseOwner);
    return (jlong) lockedSurface.get();
}

2.1.4 Surface::lock
调用connect进行一些初始化逻辑
调用BufferQueueProducer.dequeueBuffer,核心逻辑,获取slot和buffer。
计算需要重新绘制渲染的区域。
调用backBuffer->lockAsync锁定buffer,和后面unlock相对称,主要做的事是将底层分配的buffer做一个map,映射到进程空间,在执行映射前会等fence完成,确保buffer其他人使用完成了.

status_t Surface::lock(
    ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds)
{
    // 。。。检测是否已经lock了(mLockBuffer不为空)

    if (!mConnectedToCpu) {
        // 调用connect,详见2.1.5
        int err = Surface::connect(NATIVE_WINDOW_API_CPU);
        if (err) {
            return err;
        }
        setUsage(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
    }

    ANativeWindowBuffer* out;
    int fenceFd = -1;
    // 调用dequeueBuffer 详见2.1.7
    status_t err = dequeueBuffer(&out, &fenceFd);
    if (err == NO_ERROR) {
        // 获取新分配的buffer
        sp<GraphicBuffer> backBuffer(GraphicBuffer::getSelf(out));
        const Rect bounds(backBuffer->width, backBuffer->height);
        // 根据入参,脏区和新建的buffer做位运算,计算出脏数据区域。如果入参为空,则新的整个buffer都是脏区域
        Region newDirtyRegion;
        if (inOutDirtyBounds) {
            newDirtyRegion.set(static_cast<Rect const&>(*inOutDirtyBounds));
            newDirtyRegion.andSelf(bounds);
        } else {
            newDirtyRegion.set(bounds);
        }

        // mPostedBuffer是上次提交的Buffer,这里类似双缓存buffer的概念,
        // mPostedBuffer为目前前台显示buffer,新dequeue的是后台在渲染的buffer
        // 这里比较buffer宽高和编码模式是否变化,没有变化才可以把前台buffer数据拷贝过来,再结合newDirtyRegion减少需要渲染的范围。
        const sp<GraphicBuffer>& frontBuffer(mPostedBuffer);
        const bool canCopyBack = (frontBuffer != nullptr &&
                backBuffer->width  == frontBuffer->width &&
                backBuffer->height == frontBuffer->height &&
                backBuffer->format == frontBuffer->format);

        if (canCopyBack) {
            // 拷贝前台区域,减少需要重新渲染的区域。
            const Region copyback(mDirtyRegion.subtract(newDirtyRegion));
            if (!copyback.isEmpty()) {
                copyBlt(backBuffer, frontBuffer, copyback, &fenceFd);
            }
        } else {
            // 如果不能拷贝前台buffer,整个区域都是需要重新渲染的
            newDirtyRegion.set(bounds);
            mDirtyRegion.clear();
            Mutex::Autolock lock(mMutex);
            for (size_t i=0 ; i<NUM_BUFFER_SLOTS ; i++) {
                mSlots[i].dirtyRegion.clear();
            }
        }


        { // scope for the lock
            Mutex::Autolock lock(mMutex);
            // 根据buffer获取slot索引
            int backBufferSlot(getSlotFromBufferLocked(backBuffer.get()));
            if (backBufferSlot >= 0) {
                Region& dirtyRegion(mSlots[backBufferSlot].dirtyRegion);
                mDirtyRegion.subtract(dirtyRegion);
                dirtyRegion = newDirtyRegion;
            }
        }

        mDirtyRegion.orSelf(newDirtyRegion);
        // 最终计算的区域通过参数返回。
        if (inOutDirtyBounds) {
            *inOutDirtyBounds = newDirtyRegion.getBounds();
        }

        void* vaddr;
        // 锁定buffer,传入了fence,这里的逻辑我们也暂时不看,等GraphicBuffer章节再介绍
        status_t res = backBuffer->lockAsync(
                GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
                newDirtyRegion.bounds(), &vaddr, fenceFd);

        if (res != 0) {
            err = INVALID_OPERATION;
        } else {
            mLockedBuffer = backBuffer;
            outBuffer->width  = backBuffer->width;
            outBuffer->height = backBuffer->height;
            outBuffer->stride = backBuffer->stride;
            outBuffer->format = backBuffer->format;
            outBuffer->bits   = vaddr;
        }
    }
    return err;
}

2.1.5 Surface::connect
经过一系列重载会调用到这个函数

int Surface::connect(
    int api, const sp<IProducerListener>& listener, bool reportBufferRemoval) {
    // 。。。
    IGraphicBufferProducer::QueueBufferOutput output;
    mReportRemovedBuffers = reportBufferRemoval;
    // 调用生产者的connect,详见2.1.6
    int err = mGraphicBufferProducer->connect(listener, api, mProducerControlledByApp, &output);
    // 从BufferQueueCore拿到存在output里面的一些变量记录到Surface里,比如宽高。
    if (!err && api == NATIVE_WINDOW_API_CPU) {
        mConnectedToCpu = true;
        // Clear the dirty region in case we're switching from a non-CPU API
        mDirtyRegion.clear();
    } else if (!err) {
        mDirtyRegion = Region::INVALID_REGION;
    }

    return err;
}  

2.1.6 BBQBufferQueueProducer::connect
主要调用的是父类的connect,我们这里直接看父类BufferQueueProducer::connect
重新计算最大buffer数,调整mSlot的几个队列。(比如如果最大buffer数扩大了,就要从unUsedSlots里移动对应数量到mFreeSlots)
计算最大Buffer到数量逻辑为mMaxAcquiredBufferCount+mMaxDequeuedBufferCount+(如果是异步模式还要加一个),这里计算出来的和配置的mMaxBufferCount更小的一个值就是最终最大buffer个数。
如果传入listener不为空就存储到变量里。

status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener,
    int api, bool producerControlledByApp, QueueBufferOutput *output) {
    // 参数有效性校验

    // 重新计算最大buffer数,更新调整mSlot
    int delta = mCore->getMaxBufferCountLocked(mCore->mAsyncMode,
            mDequeueTimeout < 0 ?
            mCore->mConsumerControlledByApp && producerControlledByApp : false,
            mCore->mMaxBufferCount) -
            mCore->getMaxBufferCountLocked();
    if (!mCore->adjustAvailableSlotsLocked(delta)) {
        BQ_LOGE("connect: BufferQueue failed to adjust the number of available "
                "slots. Delta = %d", delta);
        return BAD_VALUE;
    }

    mCore->mConnectedApi = api;

    // 把BufferQueueCore里面的参数取出来填充至output
    // 。。。
    if (listener != nullptr) {
        // 。。。如果参数listener不为空,这里记录一下listener
        mCore->mConnectedProducerListener = listener;
        mCore->mBufferReleasedCbEnabled = listener->needsReleaseNotify();
    }

    //。。。配置BufferQueueCore的一些变量
    VALIDATE_CONSISTENCY();
    return status;
}  

2.1.7 Surface::dequeueBuffer
这里有一个共享buffer模式,默认情况不用使用这种模式,从逻辑上看就是复用同一个buffer,索引存在mSharedBufferSlot。
这里核心就是通过调用mGraphicBufferProducer->dequeueBuffer从mSlots里获取一个空闲的Slot,把它变成DEQUEUE状态,用来绘制。
如果Slot里面的buffer不符合我们的条件,需要重新分配,例如Surface大小变化了,或者format变化了,所需要buffer大小不同了,那么就需要调用mGraphicBufferProducer->requestBuffer重新分配GraphicBuffer了,这个流程我们放到GraphicBuffer流程介绍。

int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {
    IGraphicBufferProducer::DequeueBufferInput dqInput;
    {
        Mutex::Autolock lock(mMutex);
        if (mReportRemovedBuffers) {
            mRemovedBuffers.clear();
        }
        // 从Surface里获取一些参数封装到DequeueBufferInput
        // 主要是宽高和format(format是图像编码格式)
        getDequeueBufferInputLocked(&dqInput);
        // 如果是共享buffer模式,并且已经分配了共享buffer,直接返回。
        if (mSharedBufferMode && mAutoRefresh && mSharedBufferSlot !=
                BufferItem::INVALID_BUFFER_SLOT) {
            sp<GraphicBuffer>& gbuf(mSlots[mSharedBufferSlot].buffer);
            if (gbuf != nullptr) {
                *buffer = gbuf.get();
                *fenceFd = -1;
                return OK;
            }
        }
    } 

    int buf = -1;
    sp<Fence> fence;
    nsecs_t startTime = systemTime();

    FrameEventHistoryDelta frameTimestamps;
    // 调用生产者dequeueBuffer 详见2.6
    status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence, dqInput.width,
            dqInput.height, dqInput.format,
            dqInput.usage, &mBufferAge,
            dqInput.getTimestamps ?
            &frameTimestamps : nullptr);
    //。。。

    sp<GraphicBuffer>& gbuf(mSlots[buf].buffer);


    if (result & IGraphicBufferProducer::RELEASE_ALL_BUFFERS) {
        freeAllBuffers();
    }
    // 我们之前是从mSlots列表里拿了一个索引,对应分配了一个Slot
    // 这里根据返回值确认是否需要重新分配Slot里面的GraphicBuffer(比如画面大小变化了,需要的buffer大小不一样了,就需要重新分配buffer)
    if ((result & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) || gbuf == nullptr) {
        if (mReportRemovedBuffers && (gbuf != nullptr)) {
            mRemovedBuffers.push_back(gbuf);
        }
        // 这个方法是分配GraphicBuffer的,这个流程我们放到GraphicBuffer到部分介绍。
        result = mGraphicBufferProducer->requestBuffer(buf, &gbuf);
        // 。。。
    }

    if (fence->isValid()) {
        // fence之前提过它的作用,
        *fenceFd = fence->dup();
    } else {
        *fenceFd = -1;
    }

    *buffer = gbuf.get();
    // 如果是共享buffer模式,需要把分配到的buffer索引存到mSharedBufferSlot
    if (mSharedBufferMode && mAutoRefresh) {
        mSharedBufferSlot = buf;
        mSharedBufferHasBeenQueued = false;
    } else if (mSharedBufferSlot == buf) {
        mSharedBufferSlot = BufferItem::INVALID_BUFFER_SLOT;
        mSharedBufferHasBeenQueued = false;
    }
    // 记录dequeue的slot索引
    mDequeuedSlots.insert(buf);

    return OK;
}

硬件渲染

ViewRootImpl的performTraversals流程中draw时候,如果是软件渲染会调用上面提到的drawSoftware,而如果是硬件渲染就是调用ThreadedRender的draw
这里省略了许多代码,包括怎么将上层canvas的操作接口转换成最终的gpu指令,这里我们重点关注dequeueBuffer流程,就省略其他的步骤了。
在这里插入图片描述

2.2 ThreadedRender::draw
我们主要关注dequeueBuffer的流程,就省略掉了其他的流程(包括把canvas的指令做转换存储等)

void draw(View view, AttachInfo attachInfo, DrawCallbacks callbacks) {
    // 。。。
    // 调用了syncAndDrawFrame
    int syncResult = syncAndDrawFrame(frameInfo);
    // 。。。
}

2.3 HardwareRender::syncAndDrawFrame
ThreadedRender是HardwareRender的子类,所以这里调用了HardwareRender的syncAndDrawFrame,这是一个native方法,通过jni调用到c++层

static int android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz,
                                                        jlong proxyPtr, jlongArray frameInfo,
                                                        jint frameInfoSize) {
    LOG_ALWAYS_FATAL_IF(frameInfoSize != UI_THREAD_FRAME_INFO_SIZE,
                        "Mismatched size expectations, given %d expected %zu", frameInfoSize,
                        UI_THREAD_FRAME_INFO_SIZE);
    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
    env->GetLongArrayRegion(frameInfo, 0, frameInfoSize, proxy->frameInfo());
    return proxy->syncAndDrawFrame();
}

2.4 DrawFrameTask::syncFrameState
RenderProxy::syncAndDrawFrame->DrawFrameTask::drawFrame->DrawFrameTask::run->DrawFrameTask::syncFrameState
中间这些流程没有我们这里关心的内容就省略了。

bool DrawFrameTask::syncFrameState(TreeInfo& info) {
    // 。。。
    // 这里的 mContext是一个CanvasContext,里面持有一个ReliableSurface
    mContext->prepareTree(info, mFrameInfo, mSyncQueued, mTargetNode);
    // 。。。
}

CanvasContext::prepareTree

void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo, int64_t syncQueued,
                                RenderNode* target) {
    // 。。。
    // mNativeSurface是一个ReliableSurface,它绑定了一个ANativeWindow,ANativeWindow封装了底层的对Buffer的一些操作,后面dequeueBuffer也是通过它来调用的
    int err = mNativeSurface->reserveNext();
    // 。。。
}

2.5 int ReliableSurface::reserveNext
我们这里出现了几个和渲染相关的窗口类,ReliableSurface,Surface,ANativeWindow。
这几个类都是一一对应的。在第二节结尾,我们提到过创建layer流程最后会通过mBlastBufferQueue.createSurface构建一个Surface,这个Surface是java层的,native层对应了一个BBQSurface,继承了Native的Surface,而Native的Surface继承了ANativeWindow。
HardwareRenderer会通过setSurface让ReliableSurface关联上前面创建的Surface(也就是ANativeWindow子类)
ANativeWindow是底层去操作GraphicBuffer的类,而Surface和ReliableSurface都是对ANativeWindow的封装。

int ReliableSurface::reserveNext() {
    if constexpr (DISABLE_BUFFER_PREFETCH) {
        return OK;
    }
    //。。。

    int fenceFd = -1;
    // ANativeWindowBuffer继承GrapherBuffer,就是我们这里需要最终申请的Buffer的一个封装。
    ANativeWindowBuffer* buffer = nullptr;

    // 就是在这里调用dequeueBuffer  
    // mWindow是一个ANativeWindow,里面的函数指针会被绑定到真实的dequeueBuffer等操作上面。
    int result = ANativeWindow_dequeueBuffer(mWindow, &buffer, &fenceFd);

    {
        std::lock_guard _lock{mMutex};
        LOG_ALWAYS_FATAL_IF(mReservedBuffer, "race condition in reserveNext");
        mReservedBuffer = buffer;
        mReservedFenceFd.reset(fenceFd);
    }

    return result;
}

dequeuBuffer流程

2.6 BufferQueueProducer::dequeueBuffer
这个方法比较长,但是做的事也不复杂,主要是一下几个:
参数校验,以及判断是不是没有可用buffer,并且正在分配,如果是则等待分配完成。然后检测一些必要入参是否为0,如果为0就使用BufferQueueCore中的默认参数。
接下去调用waitForFreeSlotThenRelock进行slot分配。
分配到slot后通过needsReallocation检测buffer是否需要以及可以重新分配。
如果需要重新分配则构建GraphicBuffer。关于GraphicBuffer我们会专门有一片文章来介绍。
回调mConsumerListener->onFrameDequeued,等待eglfence,这个eglfence是releaseBuffer时候配置的,等待gpu/hwc使用完成这个buffer。

status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* outFence,
                                        uint32_t width, uint32_t height, PixelFormat format,
                                        uint64_t usage, uint64_t* outBufferAge,
                                        FrameEventHistoryDelta* outTimestamps) {
    // 。。。参数校验

    status_t returnFlags = NO_ERROR;
    EGLDisplay eglDisplay = EGL_NO_DISPLAY;
    EGLSyncKHR eglFence = EGL_NO_SYNC_KHR;
    bool attachedByConsumer = false;

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

        // 如果没有空闲Buffer了,并且正在dequeue。
        if (mCore->mFreeBuffers.empty() && mCore->mIsAllocating) {
            mDequeueWaitingForAllocation = true;
            mCore->waitWhileAllocatingLocked(lock);
            mDequeueWaitingForAllocation = false;、
            mDequeueWaitingForAllocationCondition.notify_all();
        }

        // 入参没有配置format,使用BufferQueueCore默认format
        if (format == 0) {
            format = mCore->mDefaultBufferFormat;
        }

        usage |= mCore->mConsumerUsageBits;
        // 如果入参没有宽高,则使用BufferQueueCore默认宽高
        const bool useDefaultSize = !width && !height;
        if (useDefaultSize) {
            // 。。。
        }

        int found = BufferItem::INVALID_BUFFER_SLOT;
        while (found == BufferItem::INVALID_BUFFER_SLOT) {
            // 获取一个slot,详见2.7
            status_t status = waitForFreeSlotThenRelock(FreeSlotCaller::Dequeue, lock, &found);
            // 。。。
            const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
            // 如果不允许在dequeueBuffer过程中分配buffer,并且当前buffer需要重新分配,就放弃当前找到的slot,重新进入下一次循环通过waitForFreeSlotThenRelock找一个。
            if (!mCore->mAllowAllocation) {
                // needsReallocation用于判断buffer是否需要重新分配。详见2.8
                if (buffer->needsReallocation(width, height, format, BQ_LAYER_COUNT, usage)) {
                    if (mCore->mSharedBufferSlot == found) {
                        BQ_LOGE("dequeueBuffer: cannot re-allocate a sharedbuffer");
                        return BAD_VALUE;
                    }
                    mCore->mFreeSlots.insert(found);
                    mCore->clearBufferSlotLocked(found);
                    found = BufferItem::INVALID_BUFFER_SLOT;
                    continue;
                }
            }
        }

        const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
        // 判断是否需要重新分配buffer,共享buffer模式不允许重新分配。
        if (mCore->mSharedBufferSlot == found &&
                buffer->needsReallocation(width, height, format, BQ_LAYER_COUNT, usage)) {
            BQ_LOGE("dequeueBuffer: cannot re-allocate a shared"
                    "buffer");

            return BAD_VALUE;
        }

        // 共享模式如果这次找到的和之前不一样,把这次找到的slot放到mActiveBuffers
        if (mCore->mSharedBufferSlot != found) {
            mCore->mActiveBuffers.insert(found);
        }
        *outSlot = found;
        ATRACE_BUFFER_INDEX(found);

        attachedByConsumer = mSlots[found].mNeedsReallocation;
        mSlots[found].mNeedsReallocation = false;

        mSlots[found].mBufferState.dequeue();

        if ((buffer == nullptr) ||
                buffer->needsReallocation(width, height, format, BQ_LAYER_COUNT, usage))
        {
            // 如果需要重新分配buffer,重置一些变量,返回值里标记BUFFER_NEEDS_REALLOCATION
            mSlots[found].mAcquireCalled = false;
            mSlots[found].mGraphicBuffer = nullptr;
            mSlots[found].mRequestBufferCalled = false;
            mSlots[found].mEglDisplay = EGL_NO_DISPLAY;
            mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
            mSlots[found].mFence = Fence::NO_FENCE;
            mCore->mBufferAge = 0;
            mCore->mIsAllocating = true;

            returnFlags |= BUFFER_NEEDS_REALLOCATION;
        } else {
            // 。。。
        }
        // 。。。

        eglDisplay = mSlots[found].mEglDisplay;
        eglFence = mSlots[found].mEglFence;
        *outFence = (mCore->mSharedBufferMode &&
                mCore->mSharedBufferSlot == found) ?
                Fence::NO_FENCE : mSlots[found].mFence;
        mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
        mSlots[found].mFence = Fence::NO_FENCE;

        

        if (!(returnFlags & BUFFER_NEEDS_REALLOCATION)) {
            if (mCore->mConsumerListener != nullptr) {
                // 如果不需要重新分配buffer,这里就可以回调mConsumerListener.onFrameDequeued,dequeueBuffer基本完成了。
                mCore->mConsumerListener->onFrameDequeued(mSlots[*outSlot].mGraphicBuffer->getId());
            }
        }
    } // Autolock scope

    if (returnFlags & BUFFER_NEEDS_REALLOCATION) {
        // 构建GrahpicBuffer,我们放到GraphicBuffer到篇章介绍
        sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(
                width, height, format, BQ_LAYER_COUNT, usage,
                {mConsumerName.string(), mConsumerName.size()});

        status_t error = graphicBuffer->initCheck();

        // 。。。
        // 回调mConsumerListener.onFrameDequeued
        mCore->mConsumerListener->onFrameDequeued(mSlots[*outSlot].mGraphicBuffer->getId());

        mCore->mIsAllocating = false;
        mCore->mIsAllocatingCondition.notify_all();
        // 。。。
    }

    if (attachedByConsumer) {
        returnFlags |= BUFFER_NEEDS_REALLOCATION;
    }

    // 这里点eglFence是releaseBuffer时传过来的,如果有就要等待,否则说明buffer还在被SurfaceFlinger合成使用。
    if (eglFence != EGL_NO_SYNC_KHR) {
        EGLint result = eglClientWaitSyncKHR(eglDisplay, eglFence, 0,
                1000000000);
        // 。。。
    }

    // 。。。
    return returnFlags;
}

2.7 BufferQueueProducer::waitForFreeSlotThenRelock
这个方法主要做了以下几件事:
统计一下dequeued buffer和queued buffer个数是否超过上限。如果超过上限则等待mDequeueCondition唤醒进入下一次循环。
如果是共享buffer模式,并且共享buffer slot已经分配了,则直接返回当前的共享buffer。
从mFreeBuffers或者mFreeSlots取一个空闲的slot,如果成功则返回,失败则等待mDequeueCondition唤醒进入下一次循环。
而queueBuffer,acquireBuffer,releaseBuffer等执行后可能释放出slot的操作都会触发mDequeueCondition.notifyAll。

status_t BufferQueueProducer::waitForFreeSlotThenRelock(FreeSlotCaller caller,
    std::unique_lock<std::mutex>& lock, int* found) const {
    auto callerString = (caller == FreeSlotCaller::Dequeue) ?
            "dequeueBuffer" : "attachBuffer";
    bool tryAgain = true;
    while (tryAgain) {
        int dequeuedCount = 0;
        int acquiredCount = 0;
        // 统计dequeued和queued状态的buffer个数
        for (int s : mCore->mActiveBuffers) {
            if (mSlots[s].mBufferState.isDequeued()) {
                ++dequeuedCount;
            }
            if (mSlots[s].mBufferState.isAcquired()) {
                ++acquiredCount;
            }
        }

        // 如果DEQUEUED buffer已经到上限,就返回INVALID_OPERATION
        if (mCore->mBufferHasBeenQueued &&
                dequeuedCount >= mCore->mMaxDequeuedBufferCount) {
            // 。。。
            return INVALID_OPERATION;
        }

        *found = BufferQueueCore::INVALID_BUFFER_SLOT;

        // 检测当前队列是否已经满了,即QUEUED buffer是否到上限
        const int maxBufferCount = mCore->getMaxBufferCountLocked();
        bool tooManyBuffers = mCore->mQueue.size()
                            > static_cast<size_t>(maxBufferCount);
        if (tooManyBuffers) {
            // 如果QUEUED buffer上限了就打个日志,什么都不做在后面会挂起等待。
            BQ_LOGV("%s: queue size is %zu, waiting", callerString,
                    mCore->mQueue.size());
        } else {
            // 共享buffer模式,并且已经分配了SHARED buffer,就直接把这个slot返回即可
            if (mCore->mSharedBufferMode && mCore->mSharedBufferSlot !=
                    BufferQueueCore::INVALID_BUFFER_SLOT) {
                *found = mCore->mSharedBufferSlot;
            } else {
                // 这里分caller分Dequeue和Attach,区别就是优先使用getFreeBufferLocked还是getFreeSlotLocked分配slot。
                // 这两个方法的区别是分别从mFreeBuffers和mFreeSlots里获取slot
                // 这两个变量我们在1.5.1介绍过了,区别就是slot是否已经关联GraphicBuffer
                // 从dequeueBuffer过来就是走上面的逻辑
                if (caller == FreeSlotCaller::Dequeue) {
                    // 从FreeBuffers里获取空闲slot,详见2.7.1
                    int slot = getFreeBufferLocked();
                    if (slot != BufferQueueCore::INVALID_BUFFER_SLOT) {
                        *found = slot;
                    } else if (mCore->mAllowAllocation) {
                        // 从FreeSlots里获取空闲slot,详见2.7.2
                        *found = getFreeSlotLocked();
                    }
                } else {
                    // If we're calling this from attach, prefer free slots
                    int slot = getFreeSlotLocked();
                    if (slot != BufferQueueCore::INVALID_BUFFER_SLOT) {
                        *found = slot;
                    } else {
                        *found = getFreeBufferLocked();
                    }
                }
            }
        }

        // 如果没有找到buffer,则tryAagain为true。
        tryAgain = (*found == BufferQueueCore::INVALID_BUFFER_SLOT) ||
                tooManyBuffers;
        if (tryAgain) {
            // 如果配置的是非阻塞的,则这里直接返回一个错误码
            if ((mCore->mDequeueBufferCannotBlock || mCore->mAsyncMode) &&
                    (acquiredCount <= mCore->mMaxAcquiredBufferCount)) {
                return WOULD_BLOCK;
            }
            // 否则检测一下是否已经超时了,超时了就返回一个错误码,否则就在mDequeueCondition上等待。
            // queueBuffer,releaseBuffer等时机会触发mDequeueCondition.notifyAll()
            if (mDequeueTimeout >= 0) {
                std::cv_status result = mCore->mDequeueCondition.wait_for(lock,
                        std::chrono::nanoseconds(mDequeueTimeout));
                if (result == std::cv_status::timeout) {
                    return TIMED_OUT;
                }
            } else {
                mCore->mDequeueCondition.wait(lock);
            }
        }
    } // while (tryAgain)

    return NO_ERROR;
}

2.7.1 getFreeBufferLocked
有了上面的介绍这里其实不看代码大家也能猜到做了什么吧。就是从mFreeBuffers取一个slot索引。

int BufferQueueProducer::getFreeBufferLocked() const {
    if (mCore->mFreeBuffers.empty()) {
        return BufferQueueCore::INVALID_BUFFER_SLOT;
    }
    int slot = mCore->mFreeBuffers.front();
    mCore->mFreeBuffers.pop_front();
    return slot;
}

2.7.2 getFreeSlotLocked
逻辑同上,只不过把mFreeBuffers换成mFreeSlots。

int BufferQueueProducer::getFreeSlotLocked() const {
    if (mCore->mFreeSlots.empty()) {
        return BufferQueueCore::INVALID_BUFFER_SLOT;
    }
    int slot = *(mCore->mFreeSlots.begin());
    mCore->mFreeSlots.erase(slot);
    return slot;
}  

2.8 needsReallocation
就是判断一些属性是否发生变化了,如宽,高,编码格式等,如果变化的则buffer大小就会变化,就需要重新分配。

bool GraphicBuffer::needsReallocation(uint32_t inWidth, uint32_t inHeight,
    PixelFormat inFormat, uint32_t inLayerCount, uint64_t inUsage)
{
    if (static_cast<int>(inWidth) != width) return true;
    if (static_cast<int>(inHeight) != height) return true;
    if (inFormat != format) return true;
    if (inLayerCount != layerCount) return true;
    if ((usage & inUsage) != inUsage) return true;
    if ((usage & USAGE_PROTECTED) != (inUsage & USAGE_PROTECTED)) return true;
    return false;
}

到这里dequeueBuffer的逻辑我们就介绍完了,其实总结一下核心逻辑就是去mFreeBuffers或者mFreeSlots里获取一个空闲slot,然后判断是否需要重新为这个slot分配一个GraphicBuffer。

queueBuffer流程

接下来我们来看下queueBuffer流程,我们上面拿到buffer后,就会调用view的draw方法会做绘制了,我们调用canvas方法绘制的时候其实还并没有真正往buffer上写数据,只是记录了一些指令,cpu后续向gpu发送绘制指令,只有到gpu完成渲染这个buffer才算是生产者用完了。
3.1 这里回调到queueBuffer流程和前面到dequeueBuffer流程类似,我们就不看了。

3.2 Surface::queueBuffer
主要是调用了mGraphicBufferProducer->queueBuffer

int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) {
    // 。。。 根据buffer获取slot,校验是否有效。
    // 。。。 共享buffer模式如果共享buffer已经queue状态,直接返回。
    if (mSharedBufferSlot == i && mSharedBufferHasBeenQueued) {
        if (fenceFd >= 0) {
            close(fenceFd);
        }
        return OK;
    }

    IGraphicBufferProducer::QueueBufferOutput output;
    IGraphicBufferProducer::QueueBufferInput input;
    // 把参数封装到QueueBufferInput
    getQueueBufferInputLocked(buffer, fenceFd, mTimestamp, &input);
    applyGrallocMetadataLocked(buffer, input);
    sp<Fence> fence = input.fence;

    nsecs_t now = systemTime();
    // 调用生产者queueBuffer,详见3.3
    status_t err = mGraphicBufferProducer->queueBuffer(i, input, &output);
    mLastQueueDuration = systemTime() - now;
    if (err != OK)  {
        ALOGE("queueBuffer: error queuing buffer, %d", err);
    }
    onBufferQueuedLocked(i, fence, output);
    return err;
}  

3.3 BufferQueueProducer::queueBuffer
这个方法非常长,但是实际做的事并不复杂。
先做了一些参数校验的工作
然后通过slot的数据构造了一个BufferItem对象,修改slot的状态为queued
根据列表里最后一个BufferItem对象的mIsDroppable决定直接添加新Item到队列中还是替换最后一个Item。

mIsDroppable = mCore->mAsyncMode ||
                (mConsumerIsSurfaceFlinger && mCore->mQueueBufferCanDrop) ||
                (mCore->mLegacyBufferDrop && mCore->mQueueBufferCanDrop) ||
                (mCore->mSharedBufferMode && mCore->mSharedBufferSlot == slot)

主要还是取决于BufferQueueCore内的一些配置。
然后会唤醒等在mDequeueCondition锁上的线程,这个我们在dequeuBuffer时候看到过。
除此之外会回调frameAvailableListener或者frameReplacedListener,这里的listener在1.9介绍过就是BLASTBufferQueue。

status_t BufferQueueProducer::queueBuffer(int slot,
    const QueueBufferInput &input, QueueBufferOutput *output) {

    int64_t requestedPresentTimestamp;
    bool isAutoTimestamp;
    android_dataspace dataSpace;
    Rect crop(Rect::EMPTY_RECT);
    int scalingMode;
    uint32_t transform;
    uint32_t stickyTransform;
    sp<Fence> acquireFence;
    bool getFrameTimestamps = false;
    // 把input传过来的参数取出来放到变量里
    input.deflate(&requestedPresentTimestamp, &isAutoTimestamp, &dataSpace,
            &crop, &scalingMode, &transform, &acquireFence, &stickyTransform,
            &getFrameTimestamps);
    const Region& surfaceDamage = input.getSurfaceDamage();
    const HdrMetadata& hdrMetadata = input.getHdrMetadata();
    // 。。。

    // 封装了传入的fence
    auto acquireFenceTime = std::make_shared<FenceTime>(acquireFence);
    // 。。。

    sp<IConsumerListener> frameAvailableListener;
    sp<IConsumerListener> frameReplacedListener;
    int callbackTicket = 0;
    uint64_t currentFrameNumber = 0;
    BufferItem item;
    { // Autolock scope
        std::lock_guard<std::mutex> lock(mCore->mMutex);
        // 。。。参数校验

        // 如果是共享buffer模式,就只是确保相关变量记录准确
        if (mCore->mSharedBufferMode && mCore->mSharedBufferSlot ==
                BufferQueueCore::INVALID_BUFFER_SLOT) {
            mCore->mSharedBufferSlot = slot;
            mSlots[slot].mBufferState.mShared = true;
        }
        // 。。。

        // 检测入参中crop是否在graphicBuffer内(crop合法性校验)
        const sp<GraphicBuffer>& graphicBuffer(mSlots[slot].mGraphicBuffer);
        Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight());
        Rect croppedRect(Rect::EMPTY_RECT);
        crop.intersect(bufferRect, &croppedRect);
        if (croppedRect != crop) {
            BQ_LOGE("queueBuffer: crop rect is not contained within the "
                    "buffer in slot %d", slot);
            return BAD_VALUE;
        }

        // Override UNKNOWN dataspace with consumer default
        if (dataSpace == HAL_DATASPACE_UNKNOWN) {
            dataSpace = mCore->mDefaultBufferDataSpace;
        }

        // 更新slot里面fence,修改slot状态
        mSlots[slot].mFence = acquireFence;
        mSlots[slot].mBufferState.queue();

        // 帧数统计
        ++mCore->mFrameCounter;
        currentFrameNumber = mCore->mFrameCounter;
        mSlots[slot].mFrameNumber = currentFrameNumber;
        // 初始化BufferItem的变量, 我们之前提过mQueue里面的对象便是BufferItem
        // 所以需要将slot中核心数据存入BufferItem放入到mQueue中。
        item.mAcquireCalled = mSlots[slot].mAcquireCalled;
        item.mGraphicBuffer = mSlots[slot].mGraphicBuffer;
        item.mCrop = crop;
        item.mTransform = transform &
                ~static_cast<uint32_t>(NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY);
        item.mTransformToDisplayInverse =
                (transform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY) != 0;
        item.mScalingMode = static_cast<uint32_t>(scalingMode);
        item.mTimestamp = requestedPresentTimestamp;
        item.mIsAutoTimestamp = isAutoTimestamp;
        item.mDataSpace = dataSpace;
        item.mHdrMetadata = hdrMetadata;
        item.mFrameNumber = currentFrameNumber;
        item.mSlot = slot;
        item.mFence = acquireFence;
        item.mFenceTime = acquireFenceTime;
        // 这个属性决定当item没有及时被消费,新的item来了是否可以替换它。
        item.mIsDroppable = mCore->mAsyncMode ||
                (mConsumerIsSurfaceFlinger && mCore->mQueueBufferCanDrop) ||
                (mCore->mLegacyBufferDrop && mCore->mQueueBufferCanDrop) ||
                (mCore->mSharedBufferMode && mCore->mSharedBufferSlot == slot);
        item.mSurfaceDamage = surfaceDamage;
        item.mQueuedBuffer = true;
        item.mAutoRefresh = mCore->mSharedBufferMode && mCore->mAutoRefresh;
        item.mApi = mCore->mConnectedApi;

        mStickyTransform = stickyTransform;

        // 。。。 如果是共享buffer模式,缓存共享buffer数据。

        output->bufferReplaced = false;
        if (mCore->mQueue.empty()) {
            // 如果队列中没有数据,就把新构建的BufferItem入队即可。
            mCore->mQueue.push_back(item);
            frameAvailableListener = mCore->mConsumerListener;
        } else {
            // 如果队列不为空,我们需要检测最烈最后的Item是否需要被替换
            const BufferItem& last = mCore->mQueue.itemAt(
                    mCore->mQueue.size() - 1);
            // 这个变量的逻辑可以参照上面item初始化时候的逻辑,主要取决于mCore的mQueueBufferCanDrop,或者是否是共享buffer。
            if (last.mIsDroppable) {
                // 。。。

                // 替换旧的item
                mCore->mQueue.editItemAt(mCore->mQueue.size() - 1) = item;
                frameReplacedListener = mCore->mConsumerListener;
            } else {
                mCore->mQueue.push_back(item);
                frameAvailableListener = mCore->mConsumerListener;
            }
        }

        mCore->mBufferHasBeenQueued = true;
        // 前面看dequeueBuffer的时候,如果没有空闲的slot等情况,会等待在这个条件锁上,这里完成了queueBuffer可以唤醒它尝试再去dequeueBuffer
        mCore->mDequeueCondition.notify_all();
        mCore->mLastQueuedSlot = slot;
        // 将部分信息填写至output,回传给上层函数作为结果
        output->width = mCore->mDefaultWidth;
        output->height = mCore->mDefaultHeight;
        output->transformHint = mCore->mTransformHintInUse = mCore->mTransformHint;
        output->numPendingBuffers = static_cast<uint32_t>(mCore->mQueue.size());
        output->nextFrameNumber = mCore->mFrameCounter + 1;
        // 。。。
    } // Autolock scope

    if (!mConsumerIsSurfaceFlinger) {
        item.mGraphicBuffer.clear();
    }

    // Update and get FrameEventHistory.
    nsecs_t postedTime = systemTime(SYSTEM_TIME_MONOTONIC);
    NewFrameEventsEntry newFrameEventsEntry = {
        currentFrameNumber,
        postedTime,
        requestedPresentTimestamp,
        std::move(acquireFenceTime)
    };
    //回调mConsumerListener的addAndGetFrameTimestamps
    addAndGetFrameTimestamps(&newFrameEventsEntry,
            getFrameTimestamps ? &output->frameTimestamps : nullptr);

    int connectedApi;
    sp<Fence> lastQueuedFence;

    { // scope for the lock
        std::unique_lock<std::mutex> lock(mCallbackMutex);
        while (callbackTicket != mCurrentCallbackTicket) {
            mCallbackCondition.wait(lock);
        }
        // 回调frameAvailableListener 或者 frameReplacedListener
        // 1.9我们说过这里的listener就是BLASTBufferQueue
        if (frameAvailableListener != nullptr) {
            frameAvailableListener->onFrameAvailable(item);
        } else if (frameReplacedListener != nullptr) {
            frameReplacedListener->onFrameReplaced(item);
        }

        connectedApi = mCore->mConnectedApi;
        lastQueuedFence = std::move(mLastQueueBufferFence);

        mLastQueueBufferFence = std::move(acquireFence);
        mLastQueuedCrop = item.mCrop;
        mLastQueuedTransform = item.mTransform;

        ++mCurrentCallbackTicket;
        mCallbackCondition.notify_all();
    }

    if (connectedApi == NATIVE_WINDOW_API_EGL) {
        // 如果是gpu渲染,这里需要等上一个buffer的fence唤醒。
        lastQueuedFence->waitForever("Throttling EGL Production");
    }

    return NO_ERROR;
}

队列的消费端

讲完了生产者端,再来看看消费者这边的流程。
我们前面讲过queueBuffer会回调BLASTBufferQueue::onFrameAvailable,我们就从这里开始看。
这里做一些前置介绍:Android 12 开始生产者消费者都在app侧,但是最终合成逻辑是在SurfaceFlinger,消费者拿到数据后会存储到一个Trancastion对象里,然后commit到SurfaceFlinger,由SurfaceFLinger使用。不只是渲染内容,窗口大小等属性改变都会通过Transcation来通知SurfaceFlinger。

acquireBuffer流程

4.1 BLASTBufferQueue::onFrameAvailable
mSyncedFrameNumbers不为空说明还有Transcation commit后还没有回调。
mTransactionReadyCallback不为空说明上层需要自己同步处理Transaction,不需要直接提交
如果复用一个Buffer,要先释放mSyncTranscation之前的buffer,检查当前可用Frame数量,看是否需要丢帧。(如果有多个可用帧,直接显示最后一个即可)
acquireNextBufferLocked会获取一个队列中的BufferItem,并根据它构建一个Transcation,如果传入参数为空,则会直接将Transcation apply提交给SurfaceFlinger,否则从入参中返回,详见4.2。
这里之所以有上层自己处理Transaction的情况是因为新版本Android有一套SurfaceSyncGroup的机制,可以用于同步SurfaceView等,这层逻辑在java层。
在这里插入图片描述

void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) {
    std::function<void(SurfaceComposerClient::Transaction*)> prevCallback = nullptr;
    SurfaceComposerClient::Transaction* prevTransaction = nullptr;

    {
        // buffer被消费者拿到后,主要目的是要构造一个Transaction传给SurfaceFlinger
        // SurfaceFlinger通过Transaction来更新各个layer的数据。
        // mSyncedFrameNumbers里面存的是已经构建好Transaction但是commit还没有回调
        bool waitForTransactionCallback = !mSyncedFrameNumbers.empty();
        // 上层调用方需要自己处理新构建的Transaction
        const bool syncTransactionSet = mTransactionReadyCallback != nullptr;

        if (syncTransactionSet) {
            // mAcquireSingleBuffer决定了是否复用同一个mSyncTransaction
            // 一般只有SurfaceView才会复用,mAcquireSingleBuffer才会为false
            // 如果复用的话,就把之前存在mSyncTransaction里的buffer release了,以便处理新的buffer
            if (!mAcquireSingleBuffer) {
                auto bufferData = mSyncTransaction->getAndClearBuffer(mSurfaceControl);
                if (bufferData) {
                    // releaseBuffer流程我们后面再看。
                    releaseBuffer(bufferData->generateReleaseCallbackId(),
                                bufferData->acquireFence);
                }
            }

            if (waitForTransactionCallback) {
                // 如果当前有Transaction已经commit却还没有回调,而且还有可用的Frame
                // 这时候就要释放掉可用的Frame,因为新的Frame已经准备好(就是丢帧了)
                while (mNumFrameAvailable > 0) {
                    acquireAndReleaseBuffer();
                }
            } else {
                // 等待前面的帧处理。
                while (mNumFrameAvailable > 0) {
                    BQA_LOGD("waiting until no queued buffers");
                    mCallbackCV.wait(_lock);
                }
            }
        }

        // 可用Frame记数
        mNumFrameAvailable++;
        // 如果有两个以上可用帧,就释放一个(丢帧了)
        if (waitForTransactionCallback && mNumFrameAvailable >= 2) {
            acquireAndReleaseBuffer();
        }

        // 如果上层需要自己处理Transcation
        if (syncTransactionSet) {
            // 记录当前帧需要等待commit回调
            mSyncedFrameNumbers.emplace(item.mFrameNumber);

            while (acquireNextBufferLocked(mSyncTransaction) == BufferQueue::NO_BUFFER_AVAILABLE) {
                BQA_LOGD("waiting for available buffer");
                // 在锁上等待生产者
                mCallbackCV.wait(_lock);
            }

            // 向SurfaceFlinger注册回调函数
            incStrong((void*)transactionCommittedCallbackThunk);
            mSyncTransaction->addTransactionCommittedCallback(transactionCommittedCallbackThunk,
                    static_cast<void*>(this));
            // 重置变量
            if (mAcquireSingleBuffer) {
                prevCallback = mTransactionReadyCallback;
                prevTransaction = mSyncTransaction;
                mTransactionReadyCallback = nullptr;
                mSyncTransaction = nullptr;
            }
        } else if (!waitForTransactionCallback) {
            // 获取BufferItem,构建Transcation并且直接提交
            acquireNextBufferLocked(std::nullopt);
        }
    }
    if (prevCallback) {
        // 上层自己处理Transaction的回调。
        prevCallback(prevTransaction);
    }
}

4.2 acquireNextBufferLocked
该方法主要是通过mBufferItemConsumer->acquireBuffer获取一个队列的BufferItem
然后根据获取的BufferItem构造出Transaction
如果入参transaction不为空,则将新构造的Transcation通过入参返回,否则直接将Transaction.apply异步的方式传给SurfaceFlinger。
setBuffer里面会调用setReleaseBufferCallback,注册release回调,SurfaceFlinger是通过这个回调通知Client releaseBuffer的。

status_t BLASTBufferQueue::acquireNextBufferLocked(
        const std::optional<SurfaceComposerClient::Transaction*> transaction) {
    // 。。。检查是否有可用的帧
    // 构造一个Transaction, 如果有入参,就用入参。
    SurfaceComposerClient::Transaction localTransaction;
    bool applyTransaction = true;
    SurfaceComposerClient::Transaction* t = &localTransaction;
    if (transaction) {
        t = *transaction;
        applyTransaction = false;
    }

    BufferItem bufferItem;
    // 调用acquireBuffer,获取生产者生产的BufferItem。详见4.3
    status_t status =
            mBufferItemConsumer->acquireBuffer(&bufferItem, 0 /* expectedPresent */, false);
    // 。。。异常处理

    auto buffer = bufferItem.mGraphicBuffer;
    mNumFrameAvailable--;
    BBQ_TRACE("frame=%" PRIu64, bufferItem.mFrameNumber);
    // 如果bufferItem里没有图元buffer,直接释放BufferItem后返回
    if (buffer == nullptr) {
        mBufferItemConsumer->releaseBuffer(bufferItem, Fence::NO_FENCE);
        BQA_LOGE("Buffer was empty");
        return BAD_VALUE;
    }

    // 。。。
    // 更新mLastBufferInfo,在计算脏区会用到
    mLastBufferInfo.update(true /* hasBuffer */, bufferItem.mGraphicBuffer->getWidth(),
                        bufferItem.mGraphicBuffer->getHeight(), bufferItem.mTransform,
                        bufferItem.mScalingMode, crop);

    auto releaseBufferCallback =
            std::bind(releaseBufferCallbackThunk, wp<BLASTBufferQueue>(this) /* callbackContext */,
                    std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
    sp<Fence> fence = bufferItem.mFence ? new Fence(bufferItem.mFence->dup()) : Fence::NO_FENCE;
    // 根据BufferItem里面的内容填充Transaction
    // setBuffer里面会调用setReleaseBufferCallback,注册release回调,SurfaceFlinger是通过这个回调通知Client releaseBuffer的
    t->setBuffer(mSurfaceControl, buffer, fence, bufferItem.mFrameNumber, mProducerId,
                releaseBufferCallback);
    t->setDataspace(mSurfaceControl, static_cast<ui::Dataspace>(bufferItem.mDataSpace));
    t->setHdrMetadata(mSurfaceControl, bufferItem.mHdrMetadata);
    t->setSurfaceDamageRegion(mSurfaceControl, bufferItem.mSurfaceDamage);
    // 设置Transaction回调。
    t->addTransactionCompletedCallback(transactionCallbackThunk, static_cast<void*>(this));

    mSurfaceControlsWithPendingCallback.push(mSurfaceControl);

    if (mUpdateDestinationFrame) {
        t->setDestinationFrame(mSurfaceControl, Rect(mSize));
    } else {
        const bool ignoreDestinationFrame =
                bufferItem.mScalingMode == NATIVE_WINDOW_SCALING_MODE_FREEZE;
        t->setFlags(mSurfaceControl,
                    ignoreDestinationFrame ? layer_state_t::eIgnoreDestinationFrame : 0,
                    layer_state_t::eIgnoreDestinationFrame);
    }
    t->2(mSurfaceControl, crop);
    t->setTransform(mSurfaceControl, bufferItem.mTransform);
    t->setTransformToDisplayInverse(mSurfaceControl, bufferItem.mTransformToDisplayInverse);
    t->setAutoRefresh(mSurfaceControl, bufferItem.mAutoRefresh);
    if (!bufferItem.mIsAutoTimestamp) {
        t->setDesiredPresentTime(bufferItem.mTimestamp);
    }

    // 抛弃mPendingFrameTimelines中帧序列号小于当前处理的BufferItem的项。
    while (!mPendingFrameTimelines.empty() &&
        mPendingFrameTimelines.front().first < bufferItem.mFrameNumber) {
        ATRACE_FORMAT_INSTANT("dropping stale frameNumber: %" PRIu64 " vsyncId: %" PRId64,
                            mPendingFrameTimelines.front().first,
                            mPendingFrameTimelines.front().second.vsyncId);
        mPendingFrameTimelines.pop();
    }
    // 获取当前BufferItem对应的FrameTimelineInfo,里面包含一些时间信息。
    // 如当前帧开始渲染时间,vsyncId等
    if (!mPendingFrameTimelines.empty() &&
        mPendingFrameTimelines.front().first == bufferItem.mFrameNumber) {
        ATRACE_FORMAT_INSTANT("Transaction::setFrameTimelineInfo frameNumber: %" PRIu64
                            " vsyncId: %" PRId64,
                            bufferItem.mFrameNumber,
                            mPendingFrameTimelines.front().second.vsyncId);
        t->setFrameTimelineInfo(mPendingFrameTimelines.front().second);
        mPendingFrameTimelines.pop();
    }

    {
        std::lock_guard _lock{mTimestampMutex};
        auto dequeueTime = mDequeueTimestamps.find(buffer->getId());
        if (dequeueTime != mDequeueTimestamps.end()) {
            Parcel p;
            p.writeInt64(dequeueTime->second);
            t->setMetadata(mSurfaceControl, gui::METADATA_DEQUEUE_TIME, p);
            mDequeueTimestamps.erase(dequeueTime);
        }
    }
    // mPendingTransactions里的Transcation是通过调用mergeWithNextTransaction添加的
    // 把多个帧需要的提交合并一起提交
    mergePendingTransactions(t, bufferItem.mFrameNumber);
    if (applyTransaction) {
        // 提交给SurfaceFlinger
        t->setApplyToken(mApplyToken).apply(false, true);
        mAppliedLastTransaction = true;
        mLastAppliedFrameNumber = bufferItem.mFrameNumber;
    } else {
        t->setBufferHasBarrier(mSurfaceControl, mLastAppliedFrameNumber);
        mAppliedLastTransaction = false;
    }
    // 。。。
    return OK;
}

4.3 BufferItemConsumer::acquireBuffer
主要是调用了ConsumeBase::acquireBufferLocked,此外还等待了fence,这个fence主要是用来同步生产者使用gpu渲染。

status_t BufferItemConsumer::acquireBuffer(BufferItem *item,
        nsecs_t presentWhen, bool waitForFence) {
    status_t err;

    if (!item) return BAD_VALUE;

    Mutex::Autolock _l(mMutex);

    // 调用ConsumeBase::acquireBufferLocked,相见4.4
    err = acquireBufferLocked(item, presentWhen);
    // 。。。
    // 这里要等待fence,这个fence是之前生产者传过来的,要等待gpu渲染完成。
    if (waitForFence) {
        err = item->mFence->waitForever("BufferItemConsumer::acquireBuffer");
        if (err != OK) {
            BI_LOGE("Failed to wait for fence of acquired buffer: %s (%d)",
                    strerror(-err), err);
            return err;
        }
    }

    item->mGraphicBuffer = mSlots[item->mSlot].mGraphicBuffer;

    return OK;
}

4.4 ConsumeBase::acquireBufferLocked
主要就是调用了BufferQueueConsumer::acquireBuffer来获取Buffer。

status_t ConsumerBase::acquireBufferLocked(BufferItem *item,
        nsecs_t presentWhen, uint64_t maxFrameNumber) {
    // 。。。
    // 调用BufferQueueConsumer::acquireBuffer,详见4.5
    status_t err = mConsumer->acquireBuffer(item, presentWhen, maxFrameNumber);
    if (err != NO_ERROR) {
        return err;
    }

    if (item->mGraphicBuffer != nullptr) {
        if (mSlots[item->mSlot].mGraphicBuffer != nullptr) {
            freeBufferLocked(item->mSlot);
        }
        mSlots[item->mSlot].mGraphicBuffer = item->mGraphicBuffer;
    }

    mSlots[item->mSlot].mFrameNumber = item->mFrameNumber;
    mSlots[item->mSlot].mFence = item->mFence;

    return OK;
}

4.5 BufferQueueConsumer::acquireBuffer
入参expectedPresent代表期望的时间,只有期望时间小于这个的buffer才是可以被使用的。maxFrameNumber代表最大的帧序号,只有帧序号小于这个的才可以被执行。
先根据传入的参数判断队列中第二个BufferItem是否可以被消费,如果可以的话,第一个BufferItem就可以抛弃了,根据这个逻辑循环遍历队列。
再检测最前面我们要用来消费的BufferItem是否满足入参的时间和帧序列要求,不满足就返回PRESENT_LATER错误码。
把队列最前面的BufferItem取出放到outBuffer,修改Buffer状态到acquired。
之前抛弃的帧,回调对应次数onBufferReleased

status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer,
        nsecs_t expectedPresent, uint64_t maxFrameNumber) {
    ATRACE_CALL();

    int numDroppedBuffers = 0;
    sp<IProducerListener> listener;
    {
        std::unique_lock<std::mutex> lock(mCore->mMutex);

        // 统计acquired状态buffer个数
        int numAcquiredBuffers = 0;
        for (int s : mCore->mActiveBuffers) {
            if (mSlots[s].mBufferState.isAcquired()) {
                ++numAcquiredBuffers;
            }
        }
        // 。。。看acquired状态的buffer有没有到上限

        bool sharedBufferAvailable = mCore->mSharedBufferMode &&
                mCore->mAutoRefresh && mCore->mSharedBufferSlot !=
                BufferQueueCore::INVALID_BUFFER_SLOT;

        // 检测队列中是否有BufferItem可用
        if (mCore->mQueue.empty() && !sharedBufferAvailable) {
            return NO_BUFFER_AVAILABLE;
        }

        BufferQueueCore::Fifo::iterator front(mCore->mQueue.begin());
        // 这里是用来检测是否需要抛弃一些帧的。
        if (expectedPresent != 0 && !mCore->mQueue.empty()) {
            // 如果队列中有大于一个bufferItem,就检测一下是否需要丢帧
            while (mCore->mQueue.size() > 1 && !mCore->mQueue[0].mIsAutoTimestamp) {
                // 获取队列里第二个BufferItem
                const BufferItem& bufferItem(mCore->mQueue[1]);

                // 如果入参最大帧序列比当前帧序列小,说明消费者还没准备好消费这个帧,所以不丢弃。
                if (maxFrameNumber && bufferItem.mFrameNumber > maxFrameNumber) {
                    break;
                }

                nsecs_t desiredPresent = bufferItem.mTimestamp;
                // 如果第二个bufferItem期望到时间还没有到,
                if (desiredPresent < expectedPresent - MAX_REASONABLE_NSEC ||
                        desiredPresent > expectedPresent) {
                    break;
                }

                if (!front->mIsStale) {
                    // 如果当前第二个bufferItem都已经到执行时间了,那就把第一个抛弃了。
                    mSlots[front->mSlot].mBufferState.freeQueued();

                    // 。。。 处理共享Buffer模式的情况

                    if (mCore->mBufferReleasedCbEnabled) {
                        listener = mCore->mConnectedProducerListener;
                    }
                    // 记录丢弃BuffferItem个数
                    ++numDroppedBuffers;
                }

                mCore->mQueue.erase(front);
                front = mCore->mQueue.begin();
            }

            // 根据入参检测第一个buffer是否到了可以使用的时间
            nsecs_t desiredPresent = front->mTimestamp;
            bool bufferIsDue = desiredPresent <= expectedPresent ||
                    desiredPresent > expectedPresent + MAX_REASONABLE_NSEC;
            bool consumerIsReady = maxFrameNumber > 0 ?
                    front->mFrameNumber <= maxFrameNumber : true;
            if (!bufferIsDue || !consumerIsReady) {
                // 如果第一个Buffer的时间还没有到,返回状态码PRESENT_LATER
                return PRESENT_LATER;
            }
        }

        int slot = BufferQueueCore::INVALID_BUFFER_SLOT;

        if (sharedBufferAvailable && mCore->mQueue.empty()) {
            // 如果是共享Buffer模式,并且队列是空的,如果当前正在分配Buffer,就需要等分配完后继续
            mCore->waitWhileAllocatingLocked(lock);

            slot = mCore->mSharedBufferSlot;

            // 。。。将共享Buffer的数据拷贝到出参outBuffer
        } else if (acquireNonDroppableBuffer && front->mIsDroppable) {
            BQ_LOGV("acquireBuffer: front buffer is not droppable");
            return NO_BUFFER_AVAILABLE;
        } else {
            // 正常走这里,将从队列最前面获取到的BufferItem拷贝到outBuffer
            slot = front->mSlot;
            *outBuffer = *front;
        }

        if (!outBuffer->mIsStale) {
            mSlots[slot].mAcquireCalled = true;
            // 修改Buffer状态
            if (mCore->mQueue.empty()) {
                mSlots[slot].mBufferState.acquireNotInQueue();
            } else {
                mSlots[slot].mBufferState.acquire();
            }
            mSlots[slot].mFence = Fence::NO_FENCE;
        }

        // 如果这个buffer之前已经被消费者acquire,防止mGraphicBuffer被重复map
        if (outBuffer->mAcquireCalled) {
            outBuffer->mGraphicBuffer = nullptr;
        }

        mCore->mQueue.erase(front);

        // 前面可能丢弃了一些帧,就会释放出一些buffer,这里可以唤醒dequeueBuffer的锁。
        mCore->mDequeueCondition.notify_all();
    }

    if (listener != nullptr) {
        // 前面可能丢弃了一些帧,这里需要回调对应次数的onBufferReleased
        for (int i = 0; i < numDroppedBuffers; ++i) {
            listener->onBufferReleased();
        }
    }

    return NO_ERROR;
}

releaseBuffer流程

介绍完了acquireBuffer,我们再来看看releaseBuffer的流程。

在4.2的流程中,我们提到为Transaction去setBuffer的时候我们会调用setReleaseBufferCallback,releaseBuffer就是SurfaceFlinger通过这里来回调的。
我们就从回调这里开始看
5.1 releaseBufferCallback
在这里插入图片描述

void BLASTBufferQueue::releaseBufferCallback(
        const ReleaseCallbackId& id, const sp<Fence>& releaseFence,
        std::optional<uint32_t> currentMaxAcquiredBufferCount) {
    std::lock_guard _lock{mMutex};
    BBQ_TRACE();
    // 详见5.2
    releaseBufferCallbackLocked(id, releaseFence, currentMaxAcquiredBufferCount,
                                false /* fakeRelease */);
}

5.2 releaseBufferCallbackLocked
会对EGL渲染的队列保留一些缓冲区(根据注释,当配置刷新率低于最大刷新率时这样可以防止更高延迟,具体什么原理也没有去研究了)
主要是调用了releaseBuffer去释放Buffer

void BLASTBufferQueue::releaseBufferCallbackLocked(
        const ReleaseCallbackId& id, const sp<Fence>& releaseFence,
        std::optional<uint32_t> currentMaxAcquiredBufferCount, bool fakeRelease) {

    // 计算需要保留的缓冲区数量(当配置刷新率低于最大刷新率时这样可以防止更高延迟)
    const auto it = mSubmitted.find(id);
    const bool isEGL = it != mSubmitted.end() && it->second.mApi == NATIVE_WINDOW_API_EGL;

    if (currentMaxAcquiredBufferCount) {
        mCurrentMaxAcquiredBufferCount = *currentMaxAcquiredBufferCount;
    }

    const uint32_t numPendingBuffersToHold =
            isEGL ? std::max(0, mMaxAcquiredBuffers - (int32_t)mCurrentMaxAcquiredBufferCount) : 0;

    auto rb = ReleasedBuffer{id, releaseFence};
    if (std::find(mPendingRelease.begin(), mPendingRelease.end(), rb) == mPendingRelease.end()) {
        mPendingRelease.emplace_back(rb);
        if (fakeRelease) {
            BQA_LOGE("Faking releaseBufferCallback from transactionCompleteCallback %" PRIu64,
                    id.framenumber);
            BBQ_TRACE("FakeReleaseCallback");
        }
    }

    while (mPendingRelease.size() > numPendingBuffersToHold) {
        const auto releasedBuffer = mPendingRelease.front();
        mPendingRelease.pop_front();
        // 调用releaseBuffer,详见5.3
        releaseBuffer(releasedBuffer.callbackId, releasedBuffer.releaseFence);
        // 如果没有同步的帧在处理,直接调用acquireNextBufferLocked去apply下一帧
        if (mSyncedFrameNumbers.empty()) {
            acquireNextBufferLocked(std::nullopt);
        }
    }

    mCallbackCV.notify_all();
}

5.3 BLASTBufferQueue::releaseBuffer
调用mBufferItemConsumer->releaseBuffer

void BLASTBufferQueue::releaseBuffer(const ReleaseCallbackId& callbackId,
                                 const sp<Fence>& releaseFence) {
    auto it = mSubmitted.find(callbackId);
    if (it == mSubmitted.end()) {
        BQA_LOGE("ERROR: releaseBufferCallback without corresponding submitted buffer %s",
                callbackId.to_string().c_str());
        return;
    }
    mNumAcquired--;
    // 调用BufferItemConsumer::releaseBuffer,详见5.4
    mBufferItemConsumer->releaseBuffer(it->second, releaseFence);
    mSubmitted.erase(it);
    mSyncedFrameNumbers.erase(callbackId.framenumber);
}

5.4 BufferItemConsumer::releaseBuffer
把releaseFence里面的fence更新到BufferItem的fence,dequeueBuffer时候需要等待这个fence,虽然cpu角度SurfaceFlinger已经使用完成这个Buffer,但是可能gpu或者hwc还在使用。
主要逻辑在releaseBufferLocked,详见5.5

status_t BufferItemConsumer::releaseBuffer(const BufferItem &item,
    const sp<Fence>& releaseFence) {
    status_t err;

    Mutex::Autolock _l(mMutex);
    // 把releaseFence里面的fence更新到BufferItem的fence
    err = addReleaseFenceLocked(item.mSlot, item.mGraphicBuffer, releaseFence);
    if (err != OK) {
        BI_LOGE("Failed to addReleaseFenceLocked");
    }
    // 调用releaseBufferLocked,详见5.5
    err = releaseBufferLocked(item.mSlot, item.mGraphicBuffer, EGL_NO_DISPLAY,
            EGL_NO_SYNC_KHR);
    // 。。。
    return err;
}

5.5 ConsumerBase::releaseBufferLocked
调用BufferQueueConsumer::releaseBuffer

status_t ConsumerBase::releaseBufferLocked(
    int slot, const sp<GraphicBuffer> graphicBuffer,
    EGLDisplay display, EGLSyncKHR eglFence) {
    // 。。。
    // 调用BufferQueueConsumer::releaseBuffer,详见5.6
    status_t err = mConsumer->releaseBuffer(slot, mSlots[slot].mFrameNumber,
            display, eglFence, mSlots[slot].mFence);
    if (err == IGraphicBufferConsumer::STALE_BUFFER_SLOT) {
        freeBufferLocked(slot);
    }

    mPrevFinalReleaseFence = mSlots[slot].mFence;
    mSlots[slot].mFence = Fence::NO_FENCE;

    return err;
}

5.6 BufferQueueConsumer::releaseBuffer
主要工作就是把slot号放到空闲队列里。
然后回调listener->onBufferReleased

status_t BufferQueueConsumer::releaseBuffer(int slot, uint64_t frameNumber,
        const sp<Fence>& releaseFence, EGLDisplay eglDisplay,
        EGLSyncKHR eglFence) {
    // 。。。

    sp<IProducerListener> listener;
    { // Autolock scope
        std::lock_guard<std::mutex> lock(mCore->mMutex);

        // 帧号因为缓冲区重新分配发生变化,忽略releaseBuffer。
        if (frameNumber != mSlots[slot].mFrameNumber &&
                !mSlots[slot].mBufferState.isShared()) {
            return STALE_BUFFER_SLOT;
        }

        // 。。。要release的Buffer如果不是acquired状态,直接返回

        mSlots[slot].mEglDisplay = eglDisplay;
        mSlots[slot].mEglFence = eglFence;
        mSlots[slot].mFence = releaseFence;
        mSlots[slot].mBufferState.release();

        if (!mCore->mSharedBufferMode && mSlots[slot].mBufferState.isFree()) {
            mSlots[slot].mBufferState.mShared = false;
        }
        // 把buffer放到空闲队列里。
        if (!mSlots[slot].mBufferState.isShared()) {
            mCore->mActiveBuffers.erase(slot);
            mCore->mFreeBuffers.push_back(slot);
        }

        if (mCore->mBufferReleasedCbEnabled) {
            listener = mCore->mConnectedProducerListener;
        }

        mCore->mDequeueCondition.notify_all();
    } // Autolock scope

    // 回调listener.onBufferReleased
    if (listener != nullptr) {
        listener->onBufferReleased();
    }

    return NO_ERROR;
}

小结

我们这篇文章主要介绍了BlastBufferQueue队列以及生产者消费者对象的构造,一些核心的变量含义,以及他们的核心流程dequeuBuffer,queueBuffer,acquireBuffer,releaseBuffer。

  • 34
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值