// dequeueBuffer gets the next buffer slot index for the producer to use.
// If a buffer slot is available then that slot index is written to the
// location pointed to by the buf argument and a status of OK is returned.
// If no slot is available then a status of -EBUSY is returned and buf is
// unmodified.
//
// The outFence parameter will be updated to hold the fence associated with
// the buffer. The contents of the buffer must not be overwritten until the
// fence signals. If the fence is Fence::NO_FENCE, the buffer may be
// written immediately.
//
// The width and height parameters must be no greater than the minimum of
// GL_MAX_VIEWPORT_DIMS and GL_MAX_TEXTURE_SIZE (see: glGetIntegerv).
// An error due to invalid dimensions might not be reported until
// updateTexImage() is called. If width and height are both zero, the
// default values specified by setDefaultBufferSize() are used instead.
//
// If the format is 0, the default format will be used.
//
// The usage argument specifies gralloc buffer usage flags. The values
// are enumerated in gralloc.h, e.g. GRALLOC_USAGE_HW_RENDER. These
// will be merged with the usage flags specified by setConsumerUsageBits.
//
// The return value may be a negative error value or a non-negative
// collection of flags. If the flags are set, the return values are
// valid, but additional actions must be performed.
//
// If IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION is set, the
// producer must discard cached GraphicBuffer references for the slot
// returned in buf.
// If IGraphicBufferProducer::RELEASE_ALL_BUFFERS is set, the producer
// must discard cached GraphicBuffer references for all slots.
//
// In both cases, the producer will need to call requestBuffer to get a
// GraphicBuffer handle for the returned slot.
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) {
dequeueBuffer()
返回下一个可被生产者使用的 slot。如果 outSlot
中的 buffer 可用,则返回 NO_ERROR
。如果没有可用 slot,则返回 -EBUSY
。outFence
信号之前, buffer 内容不能被修改。如果是 Fence::NO_FENCE
,则可以立即修改 buffer。width
和 height
都是 0,则使用 setDefaultBufferSize()
设置的默认值。如果 fotmat
是 0,则使用默认值。调用 setDefaultBufferFormat()
修改默认 format,否则是 PixelFormat::PIXEL_FORMAT_RGBA_8888
。usage
指定 gralloc buffer 使用的 flag。 它会和 setConsumerUsageBits()
设置的值做“或”操作。IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION
,生产者必须丢弃 outSlot
的 GraphicBuffer 缓存。如果返回了 IGraphicBufferProducer::RELEASE_ALL_BUFFERS
,则生产者必须丢弃所有 GraphicBuffer 缓存。在这两种情况下,生产者需要调用 BufferQueueProducer::requestBuffer() 获取新的 GraphicBuffer。上面是注释说明。下面看实现。
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) {
ATRACE_CALL();
{ // Autolock scope
std::lock_guard<std::mutex> lock(mCore->mMutex);
mConsumerName = mCore->mConsumerName;
if (mCore->mIsAbandoned) {
BQ_LOGE("dequeueBuffer: BufferQueue has been abandoned");
return NO_INIT;
}
if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
BQ_LOGE("dequeueBuffer: BufferQueue has no connected producer");
return NO_INIT;
}
} // Autolock scope
connect()
设置了 mConsumerName
,不知道为啥要重复设置。消费者调用 disconnect()
时把 mIsAbandoned
设置为 false
。mConnectedApi
在生产者 connect()
时设置。if ((width && !height) || (!width && height)) {
BQ_LOGE("dequeueBuffer: invalid size: w=%u h=%u", width, height);
return BAD_VALUE;
}
BAD_VALUE
。{ // Autolock scope
std::unique_lock<std::mutex> lock(mCore->mMutex);
// If we don't have a free buffer, but we are currently allocating, we wait until allocation
// is finished such that we don't allocate in parallel.
if (mCore->mFreeBuffers.empty() && mCore->mIsAllocating) {
mDequeueWaitingForAllocation = true;
mCore->waitWhileAllocatingLocked(lock);
mDequeueWaitingForAllocation = false;
mDequeueWaitingForAllocationCondition.notify_all();
}
mFreeBuffers
是空,且 mIsAllocating
是 true
,即其他线程在分配 buffer,则等待分配完成。如果在 dequeueBuffer()
等待 BufferQueueProducer::allocateBuffers() 分配 buffer,会比自己分配等待时间更短。 if (format == 0) {
format = mCore->mDefaultBufferFormat;
}
// Enable the usage bits the consumer requested
usage |= mCore->mConsumerUsageBits;
const bool useDefaultSize = !width && !height;
if (useDefaultSize) {
width = mCore->mDefaultWidth;
height = mCore->mDefaultHeight;
if (mCore->mAutoPrerotation &&
(mCore->mTransformHintInUse & NATIVE_WINDOW_TRANSFORM_ROT_90)) {
std::swap(width, height);
}
}
format
、usage
和宽高。