status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime,
nsecs_t expectedPresentTime) {
// updateTexImage() below might drop the some buffers at the head of the queue if there is a
// buffer behind them which is timely to be presented. However this buffer may not be signaled
// yet. The code below makes sure that this wouldn't happen by setting maxFrameNumber to the
// last buffer that was signaled.
uint64_t lastSignaledFrameNumber = mLastFrameNumberReceived;
{
Mutex::Autolock lock(mQueueItemLock);
for (int i = 0; i < mQueueItems.size(); i++) {
bool fenceSignaled =
mQueueItems[i].mFenceTime->getSignalTime() != Fence::SIGNAL_TIME_PENDING;
if (!fenceSignaled) {
break;
}
lastSignaledFrameNumber = mQueueItems[i].mFrameNumber;
}
}
const uint64_t maxFrameNumberToAcquire =
std::min(mLastFrameNumberReceived.load(), lastSignaledFrameNumber);
下面的 BufferQueueLayer::updateTexImage() 会调用 BufferQueueConsumer::acquireBuffer(),而该函数根据策略可能会丢弃头部的 buffer。然而,丢弃之后的剩余的 buffer 可能还没收到信号,所以要计算 maxFrameNumberToAcquire
。
BufferQueueLayer::mQueueItems 和 mLastFrameNumberReceived
是在 onFrameAvailable()
和 onFrameReplaced()
中更新的。
status_t updateResult = mConsumer->updateTexImage(&r, expectedPresentTime, &mAutoRefresh,
&queuedBuffer, maxFrameNumberToAcquire);
BufferLayerConsumer::updateTexImage() 中先调用 BufferLayerConsumer::acquireBufferLocked() 获取 BufferItem,然后调用 BufferLayerConsumer::updateAndReleaseLocked() 更新 mCurrentTextureBuffer
同时释放上一个 buffer。
BufferLayerConsumer::bindTextureImageLocked() 中调用 RenderEngine 的 bindExternalTextureBuffer()
时传递 mCurrentTextureBuffer->graphicBuffer()
。
if (updateResult == BufferQueue::PRESENT_LATER) {
// Producer doesn't want buffer to be displayed yet. Signal a
// layer update so we check again at the next opportunity.
mFlinger->signalLayerUpdate();
return BAD_VALUE;
}
如果返回了 PRESENT_LATER
,表示未到 buffer 期望显示时间,调用 signalLayerUpdate()
后返回 BAD_VALUE
。
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) {
mConsumer->mergeSurfaceDamage(mQueueItems[0].mSurfaceDamage);
mFlinger->mTimeStats->removeTimeRecord(layerId, mQueueItems[0].mFrameNumber);
mQueueItems.removeAt(0);
mQueuedFrames--;
} else {
ALOGE("mQueuedFrames <= 0 or mQueueItems.size() = %zu\\n", mQueueItems.size());
}
}
return BAD_VALUE;
}
BUFFER_REJECTED
,先调用 mergeSurfaceDamage()
合并脏区,脏区是 TODO。removeTimeRecord()
,TimeStats 是 TODO。BAD_VALUE
。 bool more_frames_pending = false;
if (queuedBuffer) {
// Autolock scope
auto currentFrameNumber = mConsumer->getFrameNumber();
Mutex::Autolock lock(mQueueItemLock);
// Remove any stale buffers that have been dropped during
// updateTexImage
while (mQueuedFrames > 0 && mQueueItems[0].mFrameNumber != currentFrameNumber) {
mConsumer->mergeSurfaceDamage(mQueueItems[0].mSurfaceDamage);
mFlinger->mTimeStats->removeTimeRecord(layerId, mQueueItems[0].mFrameNumber);
mQueueItems.removeAt(0);
mQueuedFrames--;
}
if (mQueuedFrames > 0) {
uint64_t bufferID = mQueueItems[0].mGraphicBuffer->getId();
mFlinger->mTimeStats->setLatchTime(layerId, currentFrameNumber, latchTime);
mFlinger->mFrameTracer->traceTimestamp(layerId, bufferID, currentFrameNumber, latchTime,
FrameTracer::FrameEvent::LATCH);
mQueueItems.removeAt(0);
more_frames_pending = (mQueuedFrames.fetch_sub(1) > 1);
} else {
ALOGE("mQueuedFrames <= 0 or mQueueItems.size() = %zu\\n", mQueueItems.size());
}
}
// Decrement the queued-frames count. Signal another event if we
// have more frames pending.
if ((queuedBuffer && more_frames_pending) || mAutoRefresh) {
mFlinger->signalLayerUpdate();
}
return NO_ERROR;
}
currentFrameNumber
。getFrameNumber()
返回的是 mCurrentFrameNumber
,它又是在 BufferLayerConsumer::updateAndReleaseLocked() 中设置的,它的值是在 ConsumerBase::acquireBufferLocked()
中调用 BufferQueueConsumer::acquireBuffer() 获取的 BufferItem 的 mFrameNumber
。