Vector<BufferItem> mQueueItems;
////
void BufferQueueLayer::onFrameAvailable(const BufferItem& item) {
...
mQueueItems.push_back(item);
mQueuedFrames++;
// Wake up any pending callbacks
mLastFrameNumberReceived = item.mFrameNumber;
mQueueItemCondition.broadcast();
...
mConsumer->onBufferAvailable(item);
}
void BufferQueueLayer::onFrameReplaced(const BufferItem& item) {
...
mQueueItems.editItemAt(mQueueItems.size() - 1) = item;
// Wake up any pending callbacks
mLastFrameNumberReceived = item.mFrameNumber;
mQueueItemCondition.broadcast();
...
mConsumer->onBufferAvailable(item);
}
mQueueItems
是 BufferItem 向量。在 onFrameAvailable()
中把可用 BufferItem 插入,在 onFrameReplaced()
中把最后一个替换成新的 BufferItem。
status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime,
nsecs_t expectedPresentTime) {
...
status_t updateResult = mConsumer->updateTexImage(&r, expectedPresentTime, &mAutoRefresh,
&queuedBuffer, maxFrameNumberToAcquire);
...
} else if (updateResult == BufferLayerConsumer::BUFFER_REJECTED) {
// If the buffer has been rejected, remove it from the shadow queue
// and return early
if (queuedBuffer) {
Mutex::Autolock lock(mQueueItemLock);
if (mQueuedFrames > 0) {
...
mQueueItems.removeAt(0);
mQueuedFrames--;
} else {
ALOGE("mQueuedFrames <= 0 or mQueueItems.size() = %zu\\n", mQueueItems.size());
}
}
return BAD_VALUE;
} else if (updateResult != NO_ERROR || mUpdateTexImageFailed) {
// This can occur if something goes wrong when trying to create the
// EGLImage for this buffer. If this happens, the buffer has already
// been released, so we need to clean up the queue and bug out
// early.
if (queuedBuffer) {
Mutex::Autolock lock(mQueueItemLock);
mQueueItems.clear();
mQueuedFrames = 0;
...
}
return BAD_VALUE;
}
如果 BufferLayerConsumer::updateTexImage() 返回了 BUFFER_REJECTED
,则移除该 BufferItem。如果返回了非 NO_ERROR
,则清空 mQueueItems
。
// Remove any stale buffers that have been dropped during
// updateTexImage
while (mQueuedFrames > 0 && mQueueItems[0].mFrameNumber != currentFrameNumber) {
...
mQueueItems.removeAt(0);
mQueuedFrames--;
}
if (mQueuedFrames > 0) {
uint64_t bufferID = mQueueItems[0].mGraphicBuffer->getId();
mFlinger->mTimeStats->setLatchTime(layerId, currentFrameNumber, latchTime);
...
mQueueItems.removeAt(0);
more_frames_pending = (mQueuedFrames.fetch_sub(1) > 1);
} else {
ALOGE("mQueuedFrames <= 0 or mQueueItems.size() = %zu\\n", mQueueItems.size());
}
BufferLayerConsumer::updateTexImage() 返回 NO_ERROR
时,先把 stale buffer 都移除,判断条件是 buffer 的帧数不等于当前帧数。
如果 mQueuedFrames
大于零,则设置 latch time 后移除第一个 BufferItem。