//frameworks/native/services/surfaceflinger/Surfaceflinger.cpp
std::unique_ptr<compositionengine::CompositionEngine>mCompositionEngine;voidSurfaceFlinger::composite(nsecs_tframeTime,int64_tvsyncId)FTL_FAKE_GUARD(kMainThreadContext){ATRACE_FORMAT("%s %"PRId64,__func__,vsyncId);if(mPowerHintSessionData.sessionEnabled){mPowerHintSessionData.compositeStart=systemTime();}compositionengine::CompositionRefreshArgsrefreshArgs;constauto&displays=FTL_FAKE_GUARD(mStateLock,mDisplays);refreshArgs.outputs.reserve(displays.size());for(constauto&[_,display]:displays){refreshArgs.outputs.push_back(display->getCompositionDisplay());}mDrawingState.traverseInZOrder([&refreshArgs](Layer*layer){if(autolayerFE=layer->getCompositionEngineLayerFE())refreshArgs.layers.push_back(layerFE);});refreshArgs.layersWithQueuedFrames.reserve(mLayersWithQueuedFrames.size());for(autolayer:mLayersWithQueuedFrames){if(autolayerFE=layer->getCompositionEngineLayerFE())refreshArgs.layersWithQueuedFrames.push_back(layerFE);}refreshArgs.outputColorSetting=useColorManagement?mDisplayColorSetting:compositionengine::OutputColorSetting::kUnmanaged;refreshArgs.colorSpaceAgnosticDataspace=mColorSpaceAgnosticDataspace;refreshArgs.forceOutputColorMode=mForceColorMode;refreshArgs.updatingOutputGeometryThisFrame=mVisibleRegionsDirty;refreshArgs.updatingGeometryThisFrame=mGeometryDirty.exchange(false)||mVisibleRegionsDirty;refreshArgs.blursAreExpensive=mBlursAreExpensive;refreshArgs.internalDisplayRotationFlags=DisplayDevice::getPrimaryDisplayRotationFlags();if(CC_UNLIKELY(mDrawingState.colorMatrixChanged)){refreshArgs.colorTransformMatrix=mDrawingState.colorMatrix;mDrawingState.colorMatrixChanged=false;}refreshArgs.devOptForceClientComposition=mDebugDisableHWC;if(mDebugFlashDelay!=0){refreshArgs.devOptForceClientComposition=true;refreshArgs.devOptFlashDirtyRegionsDelay=std::chrono::milliseconds(mDebugFlashDelay);}constautoexpectedPresentTime=mExpectedPresentTime.load();constautoprevVsyncTime=mScheduler->getPreviousVsyncFrom(expectedPresentTime);constautohwcMinWorkDuration=mVsyncConfiguration->getCurrentConfigs().hwcMinWorkDuration;refreshArgs.earliestPresentTime=prevVsyncTime-hwcMinWorkDuration;refreshArgs.previousPresentFence=mPreviousPresentFences[0].fenceTime;refreshArgs.scheduledFrameTime=mScheduler->getScheduledFrameTime();refreshArgs.expectedPresentTime=expectedPresentTime;// Store the present time just before calling to the composition engine so we could notify
// the scheduler.
constautopresentTime=systemTime();mCompositionEngine->present(refreshArgs);if(mPowerHintSessionData.sessionEnabled){mPowerHintSessionData.presentEnd=systemTime();}mTimeStats->recordFrameDuration(frameTime,systemTime());if(mScheduler->onPostComposition(presentTime)){scheduleComposite(FrameHint::kNone);}postFrame();postComposition();constboolprevFrameHadClientComposition=mHadClientComposition;mHadClientComposition=mHadDeviceComposition=mReusedClientComposition=false;TimeStats::ClientCompositionRecordclientCompositionRecord;for(constauto&[_,display]:displays){constauto&state=display->getCompositionDisplay()->getState();mHadClientComposition|=state.usesClientComposition&&!state.reusedClientComposition;mHadDeviceComposition|=state.usesDeviceComposition;mReusedClientComposition|=state.reusedClientComposition;clientCompositionRecord.predicted|=(state.strategyPrediction!=CompositionStrategyPredictionState::DISABLED);clientCompositionRecord.predictionSucceeded|=(state.strategyPrediction==CompositionStrategyPredictionState::SUCCESS);}clientCompositionRecord.hadClientComposition=mHadClientComposition;clientCompositionRecord.reused=mReusedClientComposition;clientCompositionRecord.changed=prevFrameHadClientComposition!=mHadClientComposition;mTimeStats->pushCompositionStrategyState(clientCompositionRecord);// TODO: b/160583065 Enable skip validation when SF caches all client composition layers
constboolusedGpuComposition=mHadClientComposition||mReusedClientComposition;modulateVsync(&VsyncModulator::onDisplayRefresh,usedGpuComposition);mLayersWithQueuedFrames.clear();if(mLayerTracingEnabled&&mLayerTracing.flagIsSet(LayerTracing::TRACE_COMPOSITION)){// This will block and should only be used for debugging.
mLayerTracing.notify(mVisibleRegionsDirty,frameTime);}mVisibleRegionsWereDirtyThisFrame=mVisibleRegionsDirty;// Cache value for use in post-comp
mVisibleRegionsDirty=false;if(mCompositionEngine->needsAnotherUpdate()){scheduleCommit(FrameHint::kNone);}// calculate total render time for performance hinting if adpf cpu hint is enabled,
if(mPowerHintSessionData.sessionEnabled){constnsecs_tflingerDuration=(mPowerHintSessionData.presentEnd-mPowerHintSessionData.commitStart);mPowerAdvisor->sendActualWorkDuration(flingerDuration,mPowerHintSessionData.presentEnd);}}
//frameworks/native/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp
voidCompositionEngine::present(CompositionRefreshArgs&args){ATRACE_CALL();ALOGV(__FUNCTION__);preComposition(args);{// latchedLayers is used to track the set of front-end layer state that
// has been latched across all outputs for the prepare step, and is not
// needed for anything else.
LayerFESetlatchedLayers;for(constauto&output:args.outputs){output->prepare(args,latchedLayers);}}updateLayerStateFromFE(args);for(constauto&output:args.outputs){output->present(args);}}
//frameworks/native/services/surfaceflinger/CompositionEngin/src/Output.cpp
voidOutput::rebuildLayerStacks(constcompositionengine::CompositionRefreshArgs&refreshArgs,LayerFESet&layerFESet){ATRACE_CALL();ALOGV(__FUNCTION__);auto&outputState=editState();// Do nothing if this output is not enabled or there is no need to perform this update
if(!outputState.isEnabled||CC_LIKELY(!refreshArgs.updatingOutputGeometryThisFrame)){return;}// Process the layers to determine visibility and coverage
compositionengine::Output::CoverageStatecoverage{layerFESet};collectVisibleLayers(refreshArgs,coverage);// Compute the resulting coverage for this output, and store it for later
constui::Transform&tr=outputState.transform;RegionundefinedRegion{outputState.displaySpace.getBoundsAsRect()};undefinedRegion.subtractSelf(tr.transform(coverage.aboveOpaqueLayers));outputState.undefinedRegion=undefinedRegion;outputState.dirtyRegion.orSelf(coverage.dirtyRegion);}
//frameworks/native/services/surfaceflinger/CompositionEngin/src/Output.cpp
voidOutput::setColorProfile(constColorProfile&colorProfile){ui::DataspacetargetDataspace=getDisplayColorProfile()->getTargetDataspace(colorProfile.mode,colorProfile.dataspace,colorProfile.colorSpaceAgnosticDataspace);auto&outputState=editState();if(outputState.colorMode==colorProfile.mode&&outputState.dataspace==colorProfile.dataspace&&outputState.renderIntent==colorProfile.renderIntent&&outputState.targetDataspace==targetDataspace){return;}outputState.colorMode=colorProfile.mode;outputState.dataspace=colorProfile.dataspace;outputState.renderIntent=colorProfile.renderIntent;outputState.targetDataspace=targetDataspace;mRenderSurface->setBufferDataspace(colorProfile.dataspace);//设置缓存数据空间
ALOGV("Set active color mode: %s (%d), active render intent: %s (%d)",decodeColorMode(colorProfile.mode).c_str(),colorProfile.mode,decodeRenderIntent(colorProfile.renderIntent).c_str(),colorProfile.renderIntent);dirtyEntireOutput();//重置脏区
}
//frameworks/native/services/surfaceflinger/CompositionEngin/src/OutputLayer.cpp
voidOutputLayer::updateCompositionState(boolincludeGeometry,boolforceClientComposition,ui::Transform::RotationFlagsinternalDisplayRotationFlags){constauto*layerFEState=getLayerFE().getCompositionState();if(!layerFEState){return;}constauto&outputState=getOutput().getState();constauto&profile=*getOutput().getDisplayColorProfile();auto&state=editState();if(includeGeometry){// Clear the forceClientComposition flag before it is set for any
// reason. Note that since it can be set by some checks below when
// updating the geometry state, we only clear it when updating the
// geometry since those conditions for forcing client composition won't
// go away otherwise.
state.forceClientComposition=false;state.displayFrame=calculateOutputDisplayFrame();state.sourceCrop=calculateOutputSourceCrop(internalDisplayRotationFlags);state.bufferTransform=static_cast<Hwc2::Transform>(calculateOutputRelativeBufferTransform(internalDisplayRotationFlags));if((layerFEState->isSecure&&!outputState.isSecure)||(state.bufferTransform&ui::Transform::ROT_INVALID)){state.forceClientComposition=true;}}// Determine the output dependent dataspace for this layer. If it is
// colorspace agnostic, it just uses the dataspace chosen for the output to
// avoid the need for color conversion.
state.dataspace=layerFEState->isColorspaceAgnostic&&outputState.targetDataspace!=ui::Dataspace::UNKNOWN?outputState.targetDataspace:layerFEState->dataspace;// Override the dataspace transfer from 170M to sRGB if the device configuration requests this.
// We do this here instead of in buffer info so that dumpsys can still report layers that are
// using the 170M transfer. Also we only do this if the colorspace is not agnostic for the
// layer, in case the color profile uses a 170M transfer function.
if(outputState.treat170mAsSrgb&&!layerFEState->isColorspaceAgnostic&&(state.dataspace&HAL_DATASPACE_TRANSFER_MASK)==HAL_DATASPACE_TRANSFER_SMPTE_170M){state.dataspace=static_cast<ui::Dataspace>((state.dataspace&HAL_DATASPACE_STANDARD_MASK)|(state.dataspace&HAL_DATASPACE_RANGE_MASK)|HAL_DATASPACE_TRANSFER_SRGB);}// For hdr content, treat the white point as the display brightness - HDR content should not be
// boosted or dimmed.
// If the layer explicitly requests to disable dimming, then don't dim either.
if(isHdrDataspace(state.dataspace)||getOutput().getState().displayBrightnessNits==getOutput().getState().sdrWhitePointNits||getOutput().getState().displayBrightnessNits==0.f||!layerFEState->dimmingEnabled){state.dimmingRatio=1.f;state.whitePointNits=getOutput().getState().displayBrightnessNits;}else{state.dimmingRatio=std::clamp(getOutput().getState().sdrWhitePointNits/getOutput().getState().displayBrightnessNits,0.f,1.f);state.whitePointNits=getOutput().getState().sdrWhitePointNits;}// These are evaluated every frame as they can potentially change at any
// time.
if(layerFEState->forceClientComposition||!profile.isDataspaceSupported(state.dataspace)||forceClientComposition){state.forceClientComposition=true;}}
//frameworks/native/services/surfaceflinger/CompositionEngin/src/Planner.cpp
voidPlanner::plan(compositionengine::Output::OutputLayersEnumerator<compositionengine::Output>&&layers){ATRACE_CALL();std::unordered_set<LayerId>removedLayers;removedLayers.reserve(mPreviousLayers.size());std::transform(mPreviousLayers.begin(),mPreviousLayers.end(),std::inserter(removedLayers,removedLayers.begin()),[](constauto&layer){returnlayer.first;});std::vector<LayerId>currentLayerIds;for(autolayer:layers){LayerIdid=layer->getLayerFE().getSequence();if(constautolayerEntry=mPreviousLayers.find(id);layerEntry!=mPreviousLayers.end()){// Track changes from previous info
LayerState&state=layerEntry->second;ftl::Flags<LayerStateField>differences=state.update(layer);if(differences.get()==0){state.incrementFramesSinceBufferUpdate();}else{ALOGV("Layer %s changed: %s",state.getName().c_str(),differences.string().c_str());if(differences.test(LayerStateField::Buffer)){state.resetFramesSinceBufferUpdate();}else{state.incrementFramesSinceBufferUpdate();}}}else{LayerStatestate(layer);ALOGV("Added layer %s",state.getName().c_str());mPreviousLayers.emplace(std::make_pair(id,std::move(state)));}currentLayerIds.emplace_back(id);if(constautofound=removedLayers.find(id);found!=removedLayers.end()){removedLayers.erase(found);}}mCurrentLayers.clear();mCurrentLayers.reserve(currentLayerIds.size());std::transform(currentLayerIds.cbegin(),currentLayerIds.cend(),std::back_inserter(mCurrentLayers),[this](LayerIdid){LayerState*state=&mPreviousLayers.at(id);state->getOutputLayer()->editState().overrideInfo={};returnstate;});constNonBufferHashhash=getNonBufferHash(mCurrentLayers);mFlattenedHash=mFlattener.flattenLayers(mCurrentLayers,hash,std::chrono::steady_clock::now());constboollayersWereFlattened=hash!=mFlattenedHash;ALOGV("[%s] Initial hash %zx flattened hash %zx",__func__,hash,mFlattenedHash);if(mPredictorEnabled){mPredictedPlan=mPredictor.getPredictedPlan(layersWereFlattened?std::vector<constLayerState*>():mCurrentLayers,mFlattenedHash);if(mPredictedPlan){ALOGV("[%s] Predicting plan %s",__func__,to_string(mPredictedPlan->plan).c_str());}else{ALOGV("[%s] No prediction found\n",__func__);}}// Clean up the set of previous layers now that the view of the LayerStates in the flattener are
// up-to-date.
for(LayerIdremovedLayer:removedLayers){if(constautolayerEntry=mPreviousLayers.find(removedLayer);layerEntry!=mPreviousLayers.end()){constauto&[id,state]=*layerEntry;ALOGV("Removed layer %s",state.getName().c_str());mPreviousLayers.erase(removedLayer);}}}
//frameworks/native/services/surfaceflinger/CompositionEngin/src/Output.cpp
voidOutput::writeCompositionState(constcompositionengine::CompositionRefreshArgs&refreshArgs){ATRACE_CALL();ALOGV(__FUNCTION__);if(!getState().isEnabled){return;}editState().earliestPresentTime=refreshArgs.earliestPresentTime;editState().previousPresentFence=refreshArgs.previousPresentFence;editState().expectedPresentTime=refreshArgs.expectedPresentTime;compositionengine::OutputLayer*peekThroughLayer=nullptr;sp<GraphicBuffer>previousOverride=nullptr;boolincludeGeometry=refreshArgs.updatingGeometryThisFrame;uint32_tz=0;booloverrideZ=false;uint64_toutputLayerHash=0;for(auto*layer:getOutputLayersOrderedByZ()){if(layer==peekThroughLayer){// No longer needed, although it should not show up again, so
// resetting it is not truly needed either.
peekThroughLayer=nullptr;// peekThroughLayer was already drawn ahead of its z order.
continue;}boolskipLayer=false;constauto&overrideInfo=layer->getState().overrideInfo;if(overrideInfo.buffer!=nullptr){if(previousOverride&&overrideInfo.buffer->getBuffer()==previousOverride){ALOGV("Skipping redundant buffer");skipLayer=true;}else{// First layer with the override buffer.
if(overrideInfo.peekThroughLayer){peekThroughLayer=overrideInfo.peekThroughLayer;// Draw peekThroughLayer first.
overrideZ=true;includeGeometry=true;constexprboolisPeekingThrough=true;peekThroughLayer->writeStateToHWC(includeGeometry,false,z++,overrideZ,isPeekingThrough);outputLayerHash^=android::hashCombine(reinterpret_cast<uint64_t>(&peekThroughLayer->getLayerFE()),z,includeGeometry,overrideZ,isPeekingThrough,peekThroughLayer->requiresClientComposition());}previousOverride=overrideInfo.buffer->getBuffer();}}constexprboolisPeekingThrough=false;layer->writeStateToHWC(includeGeometry,skipLayer,z++,overrideZ,isPeekingThrough);if(!skipLayer){outputLayerHash^=android::hashCombine(reinterpret_cast<uint64_t>(&layer->getLayerFE()),z,includeGeometry,overrideZ,isPeekingThrough,layer->requiresClientComposition());}}editState().outputLayerHash=outputLayerHash;}
//frameworks/native/services/surfaceflinger/CompositionEngin/src/Output.cpp
voidOutput::beginFrame(){auto&outputState=editState();constbooldirty=!getDirtyRegion().isEmpty();constboolempty=getOutputLayerCount()==0;constboolwasEmpty=!outputState.lastCompositionHadVisibleLayers;// If nothing has changed (!dirty), don't recompose.
// If something changed, but we don't currently have any visible layers,
// and didn't when we last did a composition, then skip it this time.
// The second rule does two things:
// - When all layers are removed from a display, we'll emit one black
// frame, then nothing more until we get new layers.
// - When a display is created with a private layer stack, we won't
// emit any black frames until a layer is added to the layer stack.
constboolmustRecompose=dirty&&!(empty&&wasEmpty);constcharflagPrefix[]={'-','+'};static_cast<void>(flagPrefix);ALOGV_IF("%s: %s composition for %s (%cdirty %cempty %cwasEmpty)",__FUNCTION__,mustRecompose?"doing":"skipping",getName().c_str(),flagPrefix[dirty],flagPrefix[empty],flagPrefix[wasEmpty]);mRenderSurface->beginFrame(mustRecompose);if(mustRecompose){outputState.lastCompositionHadVisibleLayers=!empty;}}
//frameworks/native/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
HWComposer&mHwc;status_tVirtualDisplaySurface::refreshOutputBuffer(){LOG_ALWAYS_FATAL_IF(GpuVirtualDisplayId::tryCast(mDisplayId).has_value());if(mOutputProducerSlot>=0){mSource[SOURCE_SINK]->cancelBuffer(mapProducer2SourceSlot(SOURCE_SINK,mOutputProducerSlot),mOutputFence);}intsslot;status_tresult=dequeueBuffer(SOURCE_SINK,mOutputFormat,mOutputUsage,&sslot,&mOutputFence);if(result<0)returnresult;mOutputProducerSlot=mapSource2ProducerSlot(SOURCE_SINK,sslot);// On GPU-only frames, we don't have the right output buffer acquire fence
// until after GPU calls queueBuffer(). So here we just set the buffer
// (for use in HWC prepare) but not the fence; we'll call this again with
// the proper fence once we have it.
constautohalDisplayId=HalVirtualDisplayId::tryCast(mDisplayId);LOG_FATAL_IF(!halDisplayId);result=mHwc.setOutputBuffer(*halDisplayId,Fence::NO_FENCE,mProducerBuffers[mOutputProducerSlot]);returnresult;}
//frameworks/native/services/surfaceflinger/CompositionEngin/src/Output.cpp
GpuCompositionResultOutput::prepareFrameAsync(constCompositionRefreshArgs&refreshArgs){ATRACE_CALL();ALOGV(__FUNCTION__);auto&state=editState();constauto&previousChanges=state.previousDeviceRequestedChanges;std::optional<android::HWComposer::DeviceRequestedChanges>changes;resetCompositionStrategy();autohwcResult=chooseCompositionStrategyAsync(&changes);if(state.previousDeviceRequestedSuccess){applyCompositionStrategy(previousChanges);}finishPrepareFrame();base::unique_fdbufferFence;std::shared_ptr<renderengine::ExternalTexture>buffer;updateProtectedContentState();constbooldequeueSucceeded=dequeueRenderBuffer(&bufferFence,&buffer);GpuCompositionResultcompositionResult;if(dequeueSucceeded){std::optional<base::unique_fd>optFd=composeSurfaces(Region::INVALID_REGION,refreshArgs,buffer,bufferFence);if(optFd){compositionResult.fence=std::move(*optFd);}}autochooseCompositionSuccess=hwcResult.get();constboolpredictionSucceeded=dequeueSucceeded&&changes==previousChanges;state.strategyPrediction=predictionSucceeded?CompositionStrategyPredictionState::SUCCESS:CompositionStrategyPredictionState::FAIL;if(!predictionSucceeded){ATRACE_NAME("CompositionStrategyPredictionMiss");resetCompositionStrategy();if(chooseCompositionSuccess){applyCompositionStrategy(changes);}finishPrepareFrame();// Track the dequeued buffer to reuse so we don't need to dequeue another one.
compositionResult.buffer=buffer;}else{ATRACE_NAME("CompositionStrategyPredictionHit");}state.previousDeviceRequestedChanges=std::move(changes);state.previousDeviceRequestedSuccess=chooseCompositionSuccess;returncompositionResult;}
//frameworks/native/services/surfaceflinger/CompositionEngin/src/Display.cpp
boolDisplay::chooseCompositionStrategy(std::optional<android::HWComposer::DeviceRequestedChanges>*outChanges){ATRACE_CALL();ALOGV(__FUNCTION__);if(mIsDisconnected){returnfalse;}// If we don't have a HWC display, then we are done.
constautohalDisplayId=HalDisplayId::tryCast(mId);if(!halDisplayId){returnfalse;}// Get any composition changes requested by the HWC device, and apply them.
std::optional<android::HWComposer::DeviceRequestedChanges>changes;auto&hwc=getCompositionEngine().getHwComposer();if(status_tresult=hwc.getDeviceCompositionChanges(*halDisplayId,anyLayersRequireClientComposition(),getState().earliestPresentTime,getState().previousPresentFence,getState().expectedPresentTime,outChanges);result!=NO_ERROR){ALOGE("chooseCompositionStrategy failed for %s: %d (%s)",getName().c_str(),result,strerror(-result));returnfalse;}returntrue;}
//frameworks/native/services/surfaceflinger/DisplayHardware/HWComposer.cpp
status_tHWComposer::getDeviceCompositionChanges(HalDisplayIddisplayId,boolframeUsesClientComposition,std::chrono::steady_clock::time_pointearliestPresentTime,conststd::shared_ptr<FenceTime>&previousPresentFence,nsecs_texpectedPresentTime,std::optional<android::HWComposer::DeviceRequestedChanges>*outChanges){ATRACE_CALL();RETURN_IF_INVALID_DISPLAY(displayId,BAD_INDEX);auto&displayData=mDisplayData[displayId];auto&hwcDisplay=displayData.hwcDisplay;if(!hwcDisplay->isConnected()){returnNO_ERROR;}uint32_tnumTypes=0;uint32_tnumRequests=0;hal::Errorerror=hal::Error::NONE;// First try to skip validate altogether. We can do that when
// 1. The previous frame has not been presented yet or already passed the
// earliest time to present. Otherwise, we may present a frame too early.
// 2. There is no client composition. Otherwise, we first need to render the
// client target buffer.
constboolcanSkipValidate=[&]{// We must call validate if we have client composition
if(frameUsesClientComposition){returnfalse;}// If composer supports getting the expected present time, we can skip
// as composer will make sure to prevent early presentation
if(mComposer->isSupported(Hwc2::Composer::OptionalFeature::ExpectedPresentTime)){returntrue;}// composer doesn't support getting the expected present time. We can only
// skip validate if we know that we are not going to present early.
returnstd::chrono::steady_clock::now()>=earliestPresentTime||previousPresentFence->getSignalTime()==Fence::SIGNAL_TIME_PENDING;}();displayData.validateWasSkipped=false;if(canSkipValidate){sp<Fence>outPresentFence;uint32_tstate=UINT32_MAX;error=hwcDisplay->presentOrValidate(expectedPresentTime,&numTypes,&numRequests,&outPresentFence,&state);if(!hasChangesError(error)){RETURN_IF_HWC_ERROR_FOR("presentOrValidate",error,displayId,UNKNOWN_ERROR);}if(state==1){//Present Succeeded.
std::unordered_map<HWC2::Layer*,sp<Fence>>releaseFences;error=hwcDisplay->getReleaseFences(&releaseFences);displayData.releaseFences=std::move(releaseFences);displayData.lastPresentFence=outPresentFence;displayData.validateWasSkipped=true;displayData.presentError=error;returnNO_ERROR;}// Present failed but Validate ran.
}else{error=hwcDisplay->validate(expectedPresentTime,&numTypes,&numRequests);}ALOGV("SkipValidate failed, Falling back to SLOW validate/present");if(!hasChangesError(error)){RETURN_IF_HWC_ERROR_FOR("validate",error,displayId,BAD_INDEX);}android::HWComposer::DeviceRequestedChanges::ChangedTypeschangedTypes;changedTypes.reserve(numTypes);error=hwcDisplay->getChangedCompositionTypes(&changedTypes);RETURN_IF_HWC_ERROR_FOR("getChangedCompositionTypes",error,displayId,BAD_INDEX);autodisplayRequests=static_cast<hal::DisplayRequest>(0);android::HWComposer::DeviceRequestedChanges::LayerRequestslayerRequests;layerRequests.reserve(numRequests);error=hwcDisplay->getRequests(&displayRequests,&layerRequests);RETURN_IF_HWC_ERROR_FOR("getRequests",error,displayId,BAD_INDEX);DeviceRequestedChanges::ClientTargetPropertyclientTargetProperty;error=hwcDisplay->getClientTargetProperty(&clientTargetProperty);outChanges->emplace(DeviceRequestedChanges{std::move(changedTypes),std::move(displayRequests),std::move(layerRequests),std::move(clientTargetProperty)});error=hwcDisplay->acceptChanges();RETURN_IF_HWC_ERROR_FOR("acceptChanges",error,displayId,BAD_INDEX);returnNO_ERROR;}
//frameworks/native/services/surfaceflinger/CompositionEngin/src/RenderSurface.cpp
voidRenderSurface::queueBuffer(base::unique_fdreadyFence){auto&state=mDisplay.getState();if(state.usesClientComposition||state.flipClientTarget){// hasFlipClientTargetRequest could return true even if we haven't
// dequeued a buffer before. Try dequeueing one if we don't have a
// buffer ready.
if(mTexture==nullptr){ALOGI("Attempting to queue a client composited buffer without one ""previously dequeued for display [%s]. Attempting to dequeue ""a scratch buffer now",mDisplay.getName().c_str());// We shouldn't deadlock here, since mTexture == nullptr only
// after a successful call to queueBuffer, or if dequeueBuffer has
// never been called.
base::unique_fdunused;dequeueBuffer(&unused);}if(mTexture==nullptr){ALOGE("No buffer is ready for display [%s]",mDisplay.getName().c_str());}else{status_tresult=mNativeWindow->queueBuffer(mNativeWindow.get(),mTexture->getBuffer()->getNativeBuffer(),dup(readyFence));if(result!=NO_ERROR){ALOGE("Error when queueing buffer for display [%s]: %d",mDisplay.getName().c_str(),result);// We risk blocking on dequeueBuffer if the primary display failed
// to queue up its buffer, so crash here.
if(!mDisplay.isVirtual()){LOG_ALWAYS_FATAL("ANativeWindow::queueBuffer failed with error: %d",result);}else{mNativeWindow->cancelBuffer(mNativeWindow.get(),mTexture->getBuffer()->getNativeBuffer(),dup(readyFence));}}mTexture=nullptr;}}status_tresult=mDisplaySurface->advanceFrame();if(result!=NO_ERROR){ALOGE("[%s] failed pushing new frame to HWC: %d",mDisplay.getName().c_str(),result);}}
//frameworks/native/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
status_tFramebufferSurface::nextBuffer(uint32_t&outSlot,sp<GraphicBuffer>&outBuffer,sp<Fence>&outFence,Dataspace&outDataspace){Mutex::Autolocklock(mMutex);BufferItemitem;status_terr=acquireBufferLocked(&item,0);if(err==BufferQueue::NO_BUFFER_AVAILABLE){mHwcBufferCache.getHwcBuffer(mCurrentBufferSlot,mCurrentBuffer,&outSlot,&outBuffer);returnNO_ERROR;}elseif(err!=NO_ERROR){ALOGE("error acquiring buffer: %s (%d)",strerror(-err),err);returnerr;}// If the BufferQueue has freed and reallocated a buffer in mCurrentSlot
// then we may have acquired the slot we already own. If we had released
// our current buffer before we call acquireBuffer then that release call
// would have returned STALE_BUFFER_SLOT, and we would have called
// freeBufferLocked on that slot. Because the buffer slot has already
// been overwritten with the new buffer all we have to do is skip the
// releaseBuffer call and we should be in the same state we'd be in if we
// had released the old buffer first.
if(mCurrentBufferSlot!=BufferQueue::INVALID_BUFFER_SLOT&&item.mSlot!=mCurrentBufferSlot){mHasPendingRelease=true;mPreviousBufferSlot=mCurrentBufferSlot;mPreviousBuffer=mCurrentBuffer;}mCurrentBufferSlot=item.mSlot;mCurrentBuffer=mSlots[mCurrentBufferSlot].mGraphicBuffer;mCurrentFence=item.mFence;outFence=item.mFence;mHwcBufferCache.getHwcBuffer(mCurrentBufferSlot,mCurrentBuffer,&outSlot,&outBuffer);outDataspace=static_cast<Dataspace>(item.mDataSpace);status_tresult=mHwc.setClientTarget(mDisplayId,outSlot,outFence,outBuffer,outDataspace);if(result!=NO_ERROR){ALOGE("error posting framebuffer: %d",result);returnresult;}returnNO_ERROR;}
HWComposer setClientTarget
调用mHwc(HWComposer)的setClientTarget方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//frameworks/native/services/surfaceflinger/DisplayHardware/HWComposer.cpp
std::unordered_map<HalDisplayId,DisplayData>mDisplayData;std::unique_ptr<HWC2::Display>hwcDisplay;status_tHWComposer::setClientTarget(HalDisplayIddisplayId,uint32_tslot,constsp<Fence>&acquireFence,constsp<GraphicBuffer>&target,ui::Dataspacedataspace){RETURN_IF_INVALID_DISPLAY(displayId,BAD_INDEX);ALOGV("%s for display %s",__FUNCTION__,to_string(displayId).c_str());auto&hwcDisplay=mDisplayData[displayId].hwcDisplay;autoerror=hwcDisplay->setClientTarget(slot,target,acquireFence,dataspace);RETURN_IF_HWC_ERROR(error,displayId,BAD_VALUE);returnNO_ERROR;}
//frameworks/native/services/surfaceflinger/CompositionEngin/src/Output.cpp
voidOutput::finishFrame(constCompositionRefreshArgs&refreshArgs,GpuCompositionResult&&result){ATRACE_CALL();ALOGV(__FUNCTION__);constauto&outputState=getState();if(!outputState.isEnabled){return;}std::optional<base::unique_fd>optReadyFence;std::shared_ptr<renderengine::ExternalTexture>buffer;base::unique_fdbufferFence;if(outputState.strategyPrediction==CompositionStrategyPredictionState::SUCCESS){optReadyFence=std::move(result.fence);}else{if(result.bufferAvailable()){buffer=std::move(result.buffer);bufferFence=std::move(result.fence);}else{updateProtectedContentState();if(!dequeueRenderBuffer(&bufferFence,&buffer)){return;}}// Repaint the framebuffer (if needed), getting the optional fence for when
// the composition completes.
optReadyFence=composeSurfaces(Region::INVALID_REGION,refreshArgs,buffer,bufferFence);}if(!optReadyFence){return;}// swap buffers (presentation)
mRenderSurface->queueBuffer(std::move(*optReadyFence));}
//frameworks/native/services/surfaceflinger/CompositionEngin/src/Output.cpp
voidOutput::postFramebuffer(){ATRACE_CALL();ALOGV(__FUNCTION__);if(!getState().isEnabled){return;}auto&outputState=editState();outputState.dirtyRegion.clear();mRenderSurface->flip();autoframe=presentAndGetFrameFences();mRenderSurface->onPresentDisplayCompleted();for(auto*layer:getOutputLayersOrderedByZ()){// The layer buffer from the previous frame (if any) is released
// by HWC only when the release fence from this frame (if any) is
// signaled. Always get the release fence from HWC first.
sp<Fence>releaseFence=Fence::NO_FENCE;if(autohwcLayer=layer->getHwcLayer()){if(autof=frame.layerFences.find(hwcLayer);f!=frame.layerFences.end()){releaseFence=f->second;}}// If the layer was client composited in the previous frame, we
// need to merge with the previous client target acquire fence.
// Since we do not track that, always merge with the current
// client target acquire fence when it is available, even though
// this is suboptimal.
// TODO(b/121291683): Track previous frame client target acquire fence.
if(outputState.usesClientComposition){releaseFence=Fence::merge("LayerRelease",releaseFence,frame.clientTargetAcquireFence);}layer->getLayerFE().onLayerDisplayed(ftl::yield<FenceResult>(std::move(releaseFence)).share());}// We've got a list of layers needing fences, that are disjoint with
// OutputLayersOrderedByZ. The best we can do is to
// supply them with the present fence.
for(auto&weakLayer:mReleasedLayers){if(constautolayer=weakLayer.promote()){layer->onLayerDisplayed(ftl::yield<FenceResult>(frame.presentFence).share());}}// Clear out the released layers now that we're done with them.
mReleasedLayers.clear();}
//frameworks/native/services/surfaceflinger/CompositionEngin/src/Planner.cpp
voidPlanner::reportFinalPlan(compositionengine::Output::OutputLayersEnumerator<compositionengine::Output>&&layers){ATRACE_CALL();if(!mPredictorEnabled){return;}PlanfinalPlan;constGraphicBuffer*currentOverrideBuffer=nullptr;boolhasSkippedLayers=false;for(autolayer:layers){if(!layer->getState().overrideInfo.buffer){continue;}constGraphicBuffer*overrideBuffer=layer->getState().overrideInfo.buffer->getBuffer().get();if(overrideBuffer!=nullptr&&overrideBuffer==currentOverrideBuffer){// Skip this layer since it is part of a previous cached set
hasSkippedLayers=true;continue;}currentOverrideBuffer=overrideBuffer;constboolforcedOrRequestedClient=layer->getState().forceClientComposition||layer->requiresClientComposition();finalPlan.addLayerType(forcedOrRequestedClient?aidl::android::hardware::graphics::composer3::Composition::CLIENT:layer->getLayerFE().getCompositionState()->compositionType);}mPredictor.recordResult(mPredictedPlan,mFlattenedHash,mCurrentLayers,hasSkippedLayers,finalPlan);}
//frameworks/native/services/surfaceflinger/CompositionEngin/src/RenderSurface.cpp
constsp<DisplaySurface>mDisplaySurface;voidRenderSurface::prepareFrame(boolusesClientComposition,boolusesDeviceComposition){constautocompositionType=[=]{usingCompositionType=DisplaySurface::CompositionType;if(usesClientComposition&&usesDeviceComposition)returnCompositionType::Mixed;if(usesClientComposition)returnCompositionType::Gpu;if(usesDeviceComposition)returnCompositionType::Hwc;// Nothing to do -- when turning the screen off we get a frame like
// this. Call it a HWC frame since we won't be doing any GPU work but
// will do a prepare/set cycle.
returnCompositionType::Hwc;}();if(status_tresult=mDisplaySurface->prepareFrame(compositionType);result!=NO_ERROR){ALOGE("updateCompositionType failed for %s: %d (%s)",mDisplay.getName().c_str(),result,strerror(-result));}}
//frameworks/native/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
status_tVirtualDisplaySurface::prepareFrame(CompositionTypecompositionType){if(GpuVirtualDisplayId::tryCast(mDisplayId)){returnNO_ERROR;}VDS_LOGW_IF(mDebugState!=DebugState::Begun,"Unexpected %s in %s state",__func__,ftl::enum_string(mDebugState).c_str());mDebugState=DebugState::Prepared;mCompositionType=compositionType;if(mForceHwcCopy&&mCompositionType==CompositionType::Gpu){// Some hardware can do RGB->YUV conversion more efficiently in hardware
// controlled by HWC than in hardware controlled by the video encoder.
// Forcing GPU-composed frames to go through an extra copy by the HWC
// allows the format conversion to happen there, rather than passing RGB
// directly to the consumer.
//
// On the other hand, when the consumer prefers RGB or can consume RGB
// inexpensively, this forces an unnecessary copy.
mCompositionType=CompositionType::Mixed;}if(mCompositionType!=mDebugLastCompositionType){VDS_LOGV("%s: composition type changed to %s",__func__,toString(mCompositionType).c_str());mDebugLastCompositionType=mCompositionType;}if(mCompositionType!=CompositionType::Gpu&&(mOutputFormat!=mDefaultOutputFormat||mOutputUsage!=GRALLOC_USAGE_HW_COMPOSER)){// We must have just switched from GPU-only to MIXED or HWC
// composition. Stop using the format and usage requested by the GPU
// driver; they may be suboptimal when HWC is writing to the output
// buffer. For example, if the output is going to a video encoder, and
// HWC can write directly to YUV, some hardware can skip a
// memory-to-memory RGB-to-YUV conversion step.
//
// If we just switched *to* GPU-only mode, we'll change the
// format/usage and get a new buffer when the GPU driver calls
// dequeueBuffer().
mOutputFormat=mDefaultOutputFormat;mOutputUsage=GRALLOC_USAGE_HW_COMPOSER;refreshOutputBuffer();}returnNO_ERROR;}
//frameworks/native/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
status_tVirtualDisplaySurface::refreshOutputBuffer(){LOG_ALWAYS_FATAL_IF(GpuVirtualDisplayId::tryCast(mDisplayId).has_value());if(mOutputProducerSlot>=0){mSource[SOURCE_SINK]->cancelBuffer(mapProducer2SourceSlot(SOURCE_SINK,mOutputProducerSlot),mOutputFence);}intsslot;status_tresult=dequeueBuffer(SOURCE_SINK,mOutputFormat,mOutputUsage,&sslot,&mOutputFence);if(result<0)returnresult;mOutputProducerSlot=mapSource2ProducerSlot(SOURCE_SINK,sslot);// On GPU-only frames, we don't have the right output buffer acquire fence
// until after GPU calls queueBuffer(). So here we just set the buffer
// (for use in HWC prepare) but not the fence; we'll call this again with
// the proper fence once we have it.
constautohalDisplayId=HalVirtualDisplayId::tryCast(mDisplayId);LOG_FATAL_IF(!halDisplayId);result=mHwc.setOutputBuffer(*halDisplayId,Fence::NO_FENCE,mProducerBuffers[mOutputProducerSlot]);returnresult;}