// releaseBuffer releases a buffer slot from the consumer back to the
// BufferQueue. This may be done while the buffer's contents are still
// being accessed. The fence will signal when the buffer is no longer
// in use. frameNumber is used to indentify the exact buffer returned.
//
// If releaseBuffer returns STALE_BUFFER_SLOT, then the consumer must free
// any references to the just-released buffer that it might have, as if it
// had received a onBuffersReleased() call with a mask set for the released
// buffer.
//
// Note that the dependencies on EGL will be removed once we switch to using
// the Android HW Sync HAL.
status_t BufferQueueConsumer::releaseBuffer(int slot, uint64_t frameNumber,
const sp<Fence>& releaseFence, EGLDisplay eglDisplay,
EGLSyncKHR eglFence) {
- 从消费者释放一个 buffer。它有可能在 buffer 内容仍然可以被访问时调用,当 buffer 不再使用时发送 fence 信号。
frameNumber
用于标识要释放的 buffer。
- 如果返回了
STALE_BUFFER_SLOT
,消费者必须释放所有引用。
if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS ||
releaseFence == nullptr) {
BQ_LOGE("releaseBuffer: slot %d out of range or fence %p NULL", slot,
releaseFence.get());
return BAD_VALUE;
}
- 检查
slot
和 releaseFence
,如果错误,则返回 BAD_VALUE
。
sp<IProducerListener> listener;
{ // Autolock scope
std::lock_guard<std::mutex> lock(mCore->mMutex);
// If the frame number has changed because the buffer has been reallocated,
// we can ignore this releaseBuffer for the old buffer.
// Ignore this for the shared buffer where the frame number can easily
// get out of sync due to the buffer being queued and acquired at the
// same time.
if (frameNumber != mSlots[slot].mFrameNumber &&
!mSlots[slot].mBufferState.isShared()) {
return STALE_BUFFER_SLOT;
}
- 如果
frameNumber
与 BufferSlot 的 mFrameNumber
不一致且该 slot 不是共享 buffer,则返回 STALE_BUFFER_SLOT
,它表示该 buffer 再分配过,我们可以忽略对旧 buffer 的释放。
- 在共享 buffer,有可能 queue 和 acquire 同时进行导致失去同步,所以对共享 buffer 不检查帧数。
if (!mSlots[slot].mBufferState.isAcquired()) {
BQ_LOGE("releaseBuffer: attempted to release buffer slot %d "
"but its state was %s", slot,
mSlots[slot].mBufferState.string());
return BAD_VALUE;
}
isAcquired()
返回 false
,表示所有权不在消费者,返回 BAD_VALUE
。
mSlots[slot].mEglDisplay = eglDisplay;
mSlots[slot].mEglFence = eglFence;
mSlots[slot].mFence = releaseFence;
mSlots[slot].mBufferState.release();
// After leaving shared buffer mode, the shared buffer will
// still be around. Mark it as no longer shared if this
// operation causes it to be free.
if (!mCore->mSharedBufferMode && mSlots[slot].mBufferState.isFree()) {
mSlots[slot].mBufferState.mShared = false;
}
- 设置 BufferSlot 的成员,调用
release()
变更 BufferState 为 FREE
。如果关闭了共享 buffer 模式,且 buffer 状态是 FREE
,则设置 mShared
为 false
。
// Don't put the shared buffer on the free list.
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
// Call back without lock held
if (listener != nullptr) {
listener->onBufferReleased();
}
return NO_ERROR;
}
- 如果该 slot 不是共享 buffer,则从
mActiveBuffers
移除,加入到 mFreeBuffers
。
- 如果启用了 buffer 释放回调,设置
listener
,回调 onBufferReleased()
。