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) 编辑 收藏 举报