Android GraphicBuffer-Fence

这里需要介绍一个伴随着GraphicBuffer的Fence,包括Fence的诞生,Fence的处理。

在前面介绍Surface的时候,提到过Surface会通过BufferQueueProducer申请GraphicBuffer,用作显存,所以我们这里看一下BufferQueueProducer/Consumer是怎么管理GraphicBuffer的。(这里有一个问题,是否可以脱离BufferQueueProducer/Consumer去使用GraphicBuffer?)

BufferQueueProducer(简称producer)和BufferQueueConsumer(简称consumer)公用BufferQueueCore(简称core);core里面有一个mSlots = struct BufferSlot[64];同时mMaxAcquiredBufferCount=1,mMaxDequeuedBufferCount=1,同时getMaxBufferCountLocked 为3或者2:

int BufferQueueCore::getMaxBufferCountLocked() const {
    int maxBufferCount = mMaxAcquiredBufferCount + mMaxDequeuedBufferCount +
            ((mAsyncMode || mDequeueBufferCannotBlock) ? 1 : 0);

    // limit maxBufferCount by mMaxBufferCount always
    maxBufferCount = std::min(mMaxBufferCount, maxBufferCount);

    return maxBufferCount;
}
//BufferQueueCore创建的时候会初始化mFreeSlots(最多3个元素), mUnusedSlots有64-3个元素

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

在APP拿到BufferQueueProducer的时候,在绘制之前,会调用BufferQueueProducer.allocateBuffers,预先分配足够的GraphicBuffer,防止在draw的时候分配造成delay;

分配Buffer的数量和mFreeSlots元素数目相同,也就是3个:

void BufferQueueProducer::allocateBuffers(uint32_t width, uint32_t height,
        PixelFormat format, uint64_t usage) {
         newBufferCount = mCore->mFreeSlots.size();
         。。。。。。
     //创建3个GraphicBuffer
for (size_t i = 0; i < newBufferCount; ++i) { sp<GraphicBuffer> graphicBuffer = new GraphicBuffer( allocWidth, allocHeight, allocFormat, BQ_LAYER_COUNT, allocUsage, allocName); status_t result = graphicBuffer->initCheck(); if (result != NO_ERROR) { BQ_LOGE("allocateBuffers: failed to allocate buffer (%u x %u, format" " %u, usage %#" PRIx64 ")", width, height, format, usage); Mutex::Autolock lock(mCore->mMutex); mCore->mIsAllocating = false; mCore->mIsAllocatingCondition.broadcast(); return; } buffers.push_back(graphicBuffer); } 。。。。。
//将新创建的GraphicBuffer添加到mSlots数组中。注意mSlots的index,这个index很重要,mSlots中的数据是和index绑定的,类似于ID;其中的graphicBuffer可能会发生变化。
for (size_t i = 0; i < newBufferCount; ++i) { if (mCore->mFreeSlots.empty()) { BQ_LOGV("allocateBuffers: a slot was occupied while " "allocating. Dropping allocated buffer."); continue; } auto slot = mCore->mFreeSlots.begin(); mCore->clearBufferSlotLocked(*slot); // Clean up the slot first mSlots[*slot].mGraphicBuffer = buffers[i]; mSlots[*slot].mFence = Fence::NO_FENCE; // freeBufferLocked puts this slot on the free slots list. Since // we then attached a buffer, move the slot to free buffer list. mCore->mFreeBuffers.push_front(*slot); BQ_LOGV("allocateBuffers: allocated a new buffer in slot %d", *slot); // Make sure the erase is done after all uses of the slot // iterator since it will be invalid after this point. mCore->mFreeSlots.erase(slot); } }

下面看一下GraphicBuffer的创建流程:

GraphicBuffer经过GrallocService->GrallocHal,在libgralloc里面分配;其中比较常见的方式是使用ION驱动进行分配,分配完毕之后还要为buffer分配Fence。

 

posted on 2020-05-24 15:47  wanglifangfang  阅读(803)  评论(0编辑  收藏  举报

导航