//frameworks/native/services/surfaceflinger/BufferQueueLayer.cpp
status_tBufferQueueLayer::updateTexImage(bool&recomputeVisibleRegions,nsecs_tlatchTime,nsecs_texpectedPresentTime){// This boolean is used to make sure that SurfaceFlinger's shadow copy
// of the buffer queue isn't modified when the buffer queue is returning
// BufferItem's that weren't actually queued. This can happen in shared
// buffer mode.
boolqueuedBuffer=false;constint32_tlayerId=getSequence();LayerRejecterr(mDrawingState,getDrawingState(),recomputeVisibleRegions,getProducerStickyTransform()!=0,mName,getTransformToDisplayInverse());if(isRemovedFromCurrentState()){expectedPresentTime=0;}// 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_tlastSignaledFrameNumber=mLastFrameNumberReceived;{Mutex::Autolocklock(mQueueItemLock);for(size_ti=0;i<mQueueItems.size();i++){boolfenceSignaled=mQueueItems[i].item.mFenceTime->getSignalTime()!=Fence::SIGNAL_TIME_PENDING;if(!fenceSignaled){break;}lastSignaledFrameNumber=mQueueItems[i].item.mFrameNumber;}}constuint64_tmaxFrameNumberToAcquire=std::min(mLastFrameNumberReceived.load(),lastSignaledFrameNumber);boolautoRefresh;status_tupdateResult=mConsumer->updateTexImage(&r,expectedPresentTime,&autoRefresh,&queuedBuffer,maxFrameNumberToAcquire);mDrawingState.autoRefresh=autoRefresh;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.
// Producer 不希望显示缓冲区。 发出图层更新的信号,以便我们在下次有机会时再次检查。
mFlinger->onLayerUpdate();// (692) SurfaceFlinger onLayerUpdate流程分析
returnBAD_VALUE;}elseif(updateResult==BufferLayerConsumer::BUFFER_REJECTED){// If the buffer has been rejected, remove it from the shadow queue
// and return early
if(queuedBuffer){Mutex::Autolocklock(mQueueItemLock);if(mQueuedFrames>0){mConsumer->mergeSurfaceDamage(mQueueItems[0].item.mSurfaceDamage);mFlinger->mTimeStats->removeTimeRecord(layerId,mQueueItems[0].item.mFrameNumber);if(mQueueItems[0].surfaceFrame){addSurfaceFrameDroppedForBuffer(mQueueItems[0].surfaceFrame);}mQueueItems.erase(mQueueItems.begin());mQueuedFrames--;}}returnBAD_VALUE;}elseif(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::Autolocklock(mQueueItemLock);for(auto&[item,surfaceFrame]:mQueueItems){if(surfaceFrame){addSurfaceFrameDroppedForBuffer(surfaceFrame);}}mQueueItems.clear();mQueuedFrames=0;mFlinger->mTimeStats->onDestroy(layerId);mFlinger->mFrameTracer->onDestroy(layerId);}// Once we have hit this state, the shadow queue may no longer
// correctly reflect the incoming BufferQueue's contents, so even if
// updateTexImage starts working, the only safe course of action is
// to continue to ignore updates.
mUpdateTexImageFailed=true;returnBAD_VALUE;}boolmore_frames_pending=false;if(queuedBuffer){// Autolock scope
autocurrentFrameNumber=mConsumer->getFrameNumber();Mutex::Autolocklock(mQueueItemLock);// Remove any stale buffers that have been dropped during
// updateTexImage
while(mQueuedFrames>0&&mQueueItems[0].item.mFrameNumber!=currentFrameNumber){mConsumer->mergeSurfaceDamage(mQueueItems[0].item.mSurfaceDamage);mFlinger->mTimeStats->removeTimeRecord(layerId,mQueueItems[0].item.mFrameNumber);if(mQueueItems[0].surfaceFrame){addSurfaceFrameDroppedForBuffer(mQueueItems[0].surfaceFrame);}mQueueItems.erase(mQueueItems.begin());mQueuedFrames--;}uint64_tbufferID=mQueueItems[0].item.mGraphicBuffer->getId();mFlinger->mTimeStats->setLatchTime(layerId,currentFrameNumber,latchTime);mFlinger->mFrameTracer->traceTimestamp(layerId,bufferID,currentFrameNumber,latchTime,FrameTracer::FrameEvent::LATCH);if(mQueueItems[0].surfaceFrame){addSurfaceFramePresentedForBuffer(mQueueItems[0].surfaceFrame,mQueueItems[0].item.mFenceTime->getSignalTime(),latchTime);}mQueueItems.erase(mQueueItems.begin());more_frames_pending=(mQueuedFrames.fetch_sub(1)>1);}// Decrement the queued-frames count. Signal another event if we
// have more frames pending.
//减少排队的帧计数。 如果我们有更多待处理的帧,则发出另一个事件的信号。
if((queuedBuffer&&more_frames_pending)||mDrawingState.autoRefresh){mFlinger->onLayerUpdate();// (692) SurfaceFlinger onLayerUpdate流程分析 | 知识管理 - PingCode
}returnNO_ERROR;}
//frameworks/native/surfaces/surfaceflienger/BufferLayerConsumer.cpp
status_tBufferLayerConsumer::updateTexImage(BufferRejecter*rejecter,nsecs_texpectedPresentTime,bool*autoRefresh,bool*queuedBuffer,uint64_tmaxFrameNumber){ATRACE_CALL();BLC_LOGV("updateTexImage");Mutex::Autolocklock(mMutex);if(mAbandoned){BLC_LOGE("updateTexImage: BufferLayerConsumer is abandoned!");returnNO_INIT;}BufferItemitem;// Acquire the next buffer.
// In asynchronous mode the list is guaranteed to be one buffer
// deep, while in synchronous mode we use the oldest buffer.
status_terr=acquireBufferLocked(&item,expectedPresentTime,maxFrameNumber);if(err!=NO_ERROR){if(err==BufferQueue::NO_BUFFER_AVAILABLE){err=NO_ERROR;}elseif(err==BufferQueue::PRESENT_LATER){// return the error, without logging
}else{BLC_LOGE("updateTexImage: acquire failed: %s (%d)",strerror(-err),err);}returnerr;}if(autoRefresh){*autoRefresh=item.mAutoRefresh;}if(queuedBuffer){*queuedBuffer=item.mQueuedBuffer;}// We call the rejecter here, in case the caller has a reason to
// not accept this buffer. This is used by SurfaceFlinger to
// reject buffers which have the wrong size
//我们在这里调用拒绝器,以防调用者有理由不接受此缓冲区, SurfaceFlinger 使用它来拒绝大小错误的缓冲区
intslot=item.mSlot;if(rejecter&&rejecter->reject(mSlots[slot].mGraphicBuffer,item)){releaseBufferLocked(slot,mSlots[slot].mGraphicBuffer);returnBUFFER_REJECTED;}// Release the previous buffer.
err=updateAndReleaseLocked(item,&mPendingRelease);if(err!=NO_ERROR){returnerr;}returnerr;}
//frameworks/native/services/surfaceflinger/BufferLayerConsumer.cpp
status_tBufferLayerConsumer::acquireBufferLocked(BufferItem*item,nsecs_tpresentWhen,uint64_tmaxFrameNumber){status_terr=ConsumerBase::acquireBufferLocked(item,presentWhen,maxFrameNumber);if(err!=NO_ERROR){returnerr;}// If item->mGraphicBuffer is not null, this buffer has not been acquired
// before, so we need to clean up old references.
if(item->mGraphicBuffer!=nullptr){std::lock_guard<std::mutex>lock(mImagesMutex);if(mImages[item->mSlot]==nullptr||mImages[item->mSlot]->getBuffer()==nullptr||mImages[item->mSlot]->getBuffer()->getId()!=item->mGraphicBuffer->getId()){mImages[item->mSlot]=std::make_shared<renderengine::impl::ExternalTexture>(item->mGraphicBuffer,mRE,renderengine::impl::ExternalTexture::Usage::READABLE);}}returnNO_ERROR;}
//frameworks/native/services/surfaceflinger/BufferLayerConsumer.cpp
status_tBufferLayerConsumer::updateAndReleaseLocked(constBufferItem&item,PendingRelease*pendingRelease){status_terr=NO_ERROR;intslot=item.mSlot;BLC_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)",mCurrentTexture,(mCurrentTextureBuffer!=nullptr&&mCurrentTextureBuffer->getBuffer()!=nullptr)?mCurrentTextureBuffer->getBuffer()->handle:0,slot,mSlots[slot].mGraphicBuffer->handle);// Hang onto the pointer so that it isn't freed in the call to
// releaseBufferLocked() if we're in shared buffer mode and both buffers are
// the same.
std::shared_ptr<renderengine::ExternalTexture>nextTextureBuffer;{std::lock_guard<std::mutex>lock(mImagesMutex);nextTextureBuffer=mImages[slot];}// release old buffer
if(mCurrentTexture!=BufferQueue::INVALID_BUFFER_SLOT){if(pendingRelease==nullptr){status_tstatus=releaseBufferLocked(mCurrentTexture,mCurrentTextureBuffer->getBuffer());if(status<NO_ERROR){BLC_LOGE("updateAndRelease: failed to release buffer: %s (%d)",strerror(-status),status);err=status;// keep going, with error raised [?]
}}else{pendingRelease->currentTexture=mCurrentTexture;pendingRelease->graphicBuffer=mCurrentTextureBuffer->getBuffer();pendingRelease->isPending=true;}}// Update the BufferLayerConsumer state.
mCurrentTexture=slot;mCurrentTextureBuffer=nextTextureBuffer;mCurrentCrop=item.mCrop;mCurrentTransform=item.mTransform;mCurrentScalingMode=item.mScalingMode;mCurrentTimestamp=item.mTimestamp;mCurrentDataSpace=static_cast<ui::Dataspace>(item.mDataSpace);mCurrentHdrMetadata=item.mHdrMetadata;mCurrentFence=item.mFence;mCurrentFenceTime=item.mFenceTime;mCurrentFrameNumber=item.mFrameNumber;mCurrentTransformToDisplayInverse=item.mTransformToDisplayInverse;mCurrentSurfaceDamage=item.mSurfaceDamage;mCurrentApi=item.mApi;computeCurrentTransformMatrixLocked();returnerr;}
//frameworks/native/libs/gui/ConsumerBase.cpp
status_tConsumerBase::releaseBufferLocked(intslot,constsp<GraphicBuffer>graphicBuffer,EGLDisplaydisplay,EGLSyncKHReglFence){if(mAbandoned){CB_LOGE("releaseBufferLocked: ConsumerBase is abandoned!");returnNO_INIT;}// If consumer no longer tracks this graphicBuffer (we received a new
// buffer on the same slot), the buffer producer is definitely no longer
// tracking it.
if(!stillTracking(slot,graphicBuffer)){returnOK;}CB_LOGV("releaseBufferLocked: slot=%d/%"PRIu64,slot,mSlots[slot].mFrameNumber);status_terr=mConsumer->releaseBuffer(slot,mSlots[slot].mFrameNumber,display,eglFence,mSlots[slot].mFence);if(err==IGraphicBufferConsumer::STALE_BUFFER_SLOT){freeBufferLocked(slot);}mPrevFinalReleaseFence=mSlots[slot].mFence;mSlots[slot].mFence=Fence::NO_FENCE;returnerr;}