Android下SF合成流程重学习之Refresh流程
引言
在前面初步分析完成了Android下SF合成流程重学习之Invalidate流程,我们接下来继续下面的分析。当有事务的更新或者有Buffer的更新便会触发后面刷新的流程,即Refresh流程!
一. onMessageRefresh
cpp
文件:frameworks/native/services/surfaceflinger/Surfaceflinger.cpp
void SurfaceFlinger::onMessageRefresh() {
ATRACE_CALL();
mRefreshPending = false;
//这里的主要逻辑是搜集需要送显的layer的情况,封装成compositionengine::CompositionRefreshArgs参数传递
//给CompositionEngine做进一步操作
compositionengine::CompositionRefreshArgs refreshArgs;
const auto& displays = ON_MAIN_THREAD(mDisplays);
// display 的数量,把当前displaydevice 记录下来
refreshArgs.outputs.reserve(displays.size());
for (const auto& [_, display] : displays) {
refreshArgs.outputs.push_back(display->getCompositionDisplay());
}
// 把当前layer记录下来
mDrawingState.traverseInZOrder([&refreshArgs](Layer* layer) {
if (auto layerFE = layer->getCompositionEngineLayerFE())
refreshArgs.layers.push_back(layerFE);
});
// 把当前有queueframe的layer记录下来, 有Buffer的layer
refreshArgs.layersWithQueuedFrames.reserve(mLayersWithQueuedFrames.size());
for (sp<Layer> layer : mLayersWithQueuedFrames) {
if (auto layerFE = layer->getCompositionEngineLayerFE())
refreshArgs.layersWithQueuedFrames.push_back(layerFE);
}
...
// 主要逻辑在present里面
mCompositionEngine->present(refreshArgs);
}
前面主要搜集需要送显的layer的情况,封装成compositionengine::CompositionRefreshArgs参数传递给CompositionEngine做进一步操作。并且最最主要合成及调用Hal composer送显的逻辑都在在present里面了。
二. CompositionEngine::present
cpp
文件:frameworks/native/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp
void CompositionEngine::present(CompositionRefreshArgs& args) {
ATRACE_CALL();
ALOGV(__FUNCTION__);
// 根据是否还有layer没有消费掉,判断再调起一次刷新
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.
LayerFESet latchedLayers;
for (const auto& output : args.outputs) {
// 计算各个区域大小以及创建hwc layer
output->prepare(args, latchedLayers);
}
}
// 更新layerCompositionState
updateLayerStateFromFE(args);
for (const auto& output : args.outputs) {
// 逻辑在output.cpp的present里面
output->present(args);
}
}
2.1 preComposition
cpp
void CompositionEngine::preComposition(CompositionRefreshArgs& args) {
ATRACE_CALL();
ALOGV(__FUNCTION__);
bool needsAnotherUpdate = false;
mRefreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
//调用了layer->onPreComposition做composition前的准备。进去看没做啥实际操作
for (auto& layer : args.layers) {
if (layer->onPreComposition(mRefreshStartTime)) {
needsAnotherUpdate = true;
}
}
mNeedsAnotherUpdate = needsAnotherUpdate;
}
其主要逻辑就是调用了layer->onPreComposition做composition前的准备。进去看没做啥实际操作。
2.2 Output::prepare
prepare主要的作用是收集可见的Layers并计算各个区域大小以及创建hwc layer!
cpp
//frameworks/native/services/surfaceflinger/CompositionEngine/src/Output.cpp
void Output::prepare(const compositionengine::CompositionRefreshArgs& refreshArgs,
LayerFESet& geomSnapshots) {
...
rebuildLayerStacks(refreshArgs, geomSnapshots);
}
void Output::rebuildLayerStacks(const compositionengine::CompositionRefreshArgs& refreshArgs,
LayerFESet& layerFESet) {
...
// Process the layers to determine visibility and coverage
compositionengine::Output::CoverageState coverage{layerFESet};
collectVisibleLayers(refreshArgs, coverage);
...
}
void Output::collectVisibleLayers(const compositionengine::CompositionRefreshArgs& refreshArgs,
compositionengine::Output::CoverageState& coverage) {
...
for (auto layer : reversed(refreshArgs.layers)) {
// Incrementally process the coverage for each layer
ensureOutputLayerIfVisible(layer, coverage);
// TODO(b/121291683): Stop early if the output is completely covered and
// no more layers could even be visible underneath the ones on top.
}
...
}
其主要逻辑在ensureOutputLayerIfVisible里面。
2.3 ensureOutputLayerIfVisible
cpp
文件:frameworks/native/services/surfaceflinger/CompositionEngine/src/Output.cpp
void Output::ensureOutputLayerIfVisible(sp<compositionengine::LayerFE>& layerFE,
compositionengine::Output::CoverageState& coverage) {
....
// 创建OutputLayer
auto result = ensureOutputLayer(prevOutputLayerIndex, layerFE);
...
}
各个layer区域的计算结果可以通过adb shell dumpsys SurfaceFlinger看到,通过区域的计算把区域为空的layer过滤掉.
ensureOutputLayer将创建Output layer,这些layer最后是要显示到屏幕上的
cpp
文件: frameworks/native/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
OutputLayer* ensureOutputLayer(std::optional<size_t> prevIndex,
const sp<LayerFE>& layerFE) {
// 判断当前的outputlayer 集合里面有没有当前的layer,如果没有则新创建一个
auto outputLayer = (prevIndex && *prevIndex <= mCurrentOutputLayersOrderedByZ.size())
? std::move(mCurrentOutputLayersOrderedByZ[*prevIndex])
: BaseOutput::createOutputLayer(layerFE);
auto result = outputLayer.get();
mPendingOutputLayersOrderedByZ.emplace_back(std::move(outputLayer));
return result;
}
文件:frameworks/native/services/surfaceflinger/CompositionEngine/src/Display.cpp
std::unique_ptr<compositionengine::OutputLayer> Display::createOutputLayer(
const sp<compositionengine::LayerFE>& layerFE) const {
auto result = impl::createOutputLayer(*this, layerFE);
if (result && mId) {
auto& hwc = getCompositionEngine().getHwComposer();
auto displayId = *mId;
// 创建hwclayer
auto hwcLayer = std::shared_ptr<HWC2::Layer>(hwc.createLayer(displayId),
[&hwc, displayId](HWC2::Layer* layer) {
hwc.destroyLayer(displayId, layer);
});
ALOGE_IF(!hwcLayer, "Failed to create a HWC layer for a HWC supported display %s",
getName().c_str());
// 更新state.hwc
result->setHwcLayer(std::move(hwcLayer));
}
return result;
}
可以看到prepare主要的作用是遍历layer计算各个区域大小,过滤掉空区域的layer以及创建hwc layer。
2.4 updateLayerStateFromFE
它的核心逻辑是跟新更新OutputlayerState的参数,即layer的状态信息
cpp
文件:frameworks/native/services/surfaceflinger/Layer.cpp
void Layer::prepareCompositionState(compositionengine::LayerFE::StateSubset subset) {
using StateSubset = compositionengine::LayerFE::StateSubset;
switch (subset) {
case StateSubset::BasicGeometry:
prepareBasicGeometryCompositionState();
break;
case StateSubset::GeometryAndContent:
prepareBasicGeometryCompositionState();
prepareGeometryCompositionState();
preparePerFrameCompositionState();
break;
case StateSubset::Content:
preparePerFrameCompositionState();
break;
case StateSubset::Cursor:
prepareCursorCompositionState();
break;
}
}C++
文件:frameworks/native/services/surfaceflinger/Layer.cpp
void Layer::prepareCompositionState(compositionengine::LayerFE::StateSubset subset) {
using StateSubset = compositionengine::LayerFE::StateSubset;
switch (subset) {
case StateSubset::BasicGeometry:
prepareBasicGeometryCompositionState();
break;
case StateSubset::GeometryAndContent:
prepareBasicGeometryCompositionState();
prepareGeometryCompositionState();
preparePerFrameCompositionState();
break;
case StateSubset::Content:
preparePerFrameCompositionState();
break;
case StateSubset::Cursor:
prepareCursorCompositionState();
break;
}
}
这部分也可以通过adb shell dumpsys SurfaceFlinger看出来有哪些属性。
三. Output::present
如果说前面的都是洒洒水,开胃菜。那么从这里开始就是大餐了。
cpp
文件:frameworks/native/services/surfaceflinger/CompositionEngine/src/Output.cpp
void Output::present(const compositionengine::CompositionRefreshArgs& refreshArgs) {
ATRACE_CALL();
ALOGV(__FUNCTION__);
//设置 Display的dataspace, colormode
updateColorProfile(refreshArgs);
// 设置outputlayer的dispFrame和sourceCrop等以及将outputlayer属性设给hwc
updateAndWriteCompositionState(refreshArgs);
// 设置display的颜色矩阵,对全屏有效
setColorTransform(refreshArgs);
// FrameBuffer里面没做啥操作
beginFrame();
// 选择合成策略,判断是device还是GPU合成,如果是device合成,直接present,如果要走GPU合成则需要validate
prepareFrame();
// 一般不走
devOptRepaintFlash(refreshArgs);
// GPU合成主要逻辑在此,device合成没做啥
finishFrame(refreshArgs);
// device合成设置release fence,GPU合成需要present给hwc
postFramebuffer();
}
先关注device合成,涉及GPU部分单独分析(简单带过)!
3.1 updateAndWriteCompositionState
cpp
文件:frameworks/native/services/surfaceflinger/CompositionEngine/src/Output.cpp
void Output::updateAndWriteCompositionState(
const compositionengine::CompositionRefreshArgs& refreshArgs) {
ATRACE_CALL();
ALOGV(__FUNCTION__);
if (!getState().isEnabled) {
return;
}
mLayerRequestingBackgroundBlur = findLayerRequestingBackgroundComposition();
// 如果是有背景模糊的layer则强制使用GPU合成
bool forceClientComposition = mLayerRequestingBackgroundBlur != nullptr;
for (auto* layer : getOutputLayersOrderedByZ()) {
// 遍历outputlayer,计算DisplayFrame, SourceCrop 等参数
layer->updateCompositionState(refreshArgs.updatingGeometryThisFrame,
refreshArgs.devOptForceClientComposition ||
forceClientComposition,
refreshArgs.internalDisplayRotationFlags);
if (mLayerRequestingBackgroundBlur == layer) {
forceClientComposition = false;
}
// 将layer属性设给hwc
layer->writeStateToHWC(refreshArgs.updatingGeometryThisFrame);
}
这部分参数也可以通过adb shell dumpsys SurfaceFlinger看到:
3.2 setColorTransform
C++
文件:frameworks/native/services/surfaceflinger/CompositionEngine/src/Display.cpp
void Display::setColorTransform(const compositionengine::CompositionRefreshArgs& args) {
Output::setColorTransform(args);
if (!mId || CC_LIKELY(!args.colorTransformMatrix)) {
return;
}
auto& hwc = getCompositionEngine().getHwComposer();
// 将上层设的colorTransformMatrix 设给hwc,这个效果作用于全屏,比如护眼模式下,改变的就是这个colorTransformMatrix
status_t result = hwc.setColorTransform(*mId, *args.colorTransformMatrix);
ALOGE_IF(result != NO_ERROR, "Failed to set color transform on display \"%s\": %d",
mId ? to_string(*mId).c_str() : "", result);
}
setColorTransform 设置颜色矩阵给屏幕,作用于屏幕显示,所有的layer都受影响,护眼效果就是改变的这个值。
3.3 beginFrame
最终调用到FramebufferSurface,并没有执行具体的逻辑:
cpp
//frameworks/native/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
status_t FramebufferSurface::beginFrame(bool /*mustRecompose*/) {
return NO_ERROR;
}
3.4 prepareFrame
它的核心逻辑是选择合成策略,判断是device还是GPU合成,如果是device合成,直接present,如果要走GPU合成则需要validate。让我们通过代码具体分析:
cpp
文件:frameworks/native/services/surfaceflinger/CompositionEngine/src/Output.cpp
void Output::prepareFrame() {
...
const auto& outputState = getState();
if (!outputState.isEnabled) {
return;
}
// 选择合成类型,如果是device合成,则跳过validate,直接present送显
chooseCompositionStrategy();
// 把合成类型送到frameBufferSurface,没啥逻辑
mRenderSurface->prepareFrame(outputState.usesClientComposition,
outputState.usesDeviceComposition);
}
void Output::chooseCompositionStrategy() {
// The base output implementation can only do client composition
// 默认使用GPU合成,针对没有hwc的设备
auto& outputState = editState();
outputState.usesClientComposition = true;
outputState.usesDeviceComposition = false;
outputState.reusedClientComposition = false;
}
文件:frameworks/native/services/surfaceflinger/CompositionEngine/src/Display.cpp
void Display::chooseCompositionStrategy() {
...
// Default to the base settings -- client composition only.
Output::chooseCompositionStrategy();
...
// Get any composition changes requested by the HWC device, and apply them.
std::optional<android::HWComposer::DeviceRequestedChanges> changes;
auto& hwc = getCompositionEngine().getHwComposer();
// 从HWC device获得合成类型的改变,这个根据hwc能力来选择device还是GPU合成
if (status_t result = hwc.getDeviceCompositionChanges(*mId, anyLayersRequireClientComposition(),
&changes);
result != NO_ERROR) {
ALOGE("chooseCompositionStrategy failed for %s: %d (%s)", getName().c_str(), result,
strerror(-result));
return;
}
//如果有变化则设置给对应的layer
if (changes) {
applyChangedTypesToLayers(changes->changedTypes);
applyDisplayRequests(changes->displayRequests);
applyLayerRequestsToLayers(changes->layerRequests);
applyClientTargetRequests(changes->clientTargetProperty);
}
// Determine what type of composition we are doing from the final state
// 决定最后的合成类型
auto& state = editState();
state.usesClientComposition = anyLayersRequireClientComposition();
state.usesDeviceComposition = !allLayersRequireClientComposition();
}
文件:frameworks/native/services/surfaceflinger/DisplayHardware/HWComposer.cpp
status_t HWComposer::getDeviceCompositionChanges(
DisplayId displayId, bool frameUsesClientComposition,
std::optional<android::HWComposer::DeviceRequestedChanges>* outChanges) {
...
if (!frameUsesClientComposition) {
sp<Fence> outPresentFence;
uint32_t state = UINT32_MAX;
// 如果所有的layer都能走device合成,则在hwc里面直接present,若有不支持device合成的情况,则走GPU合成,会走validate逻辑
error = hwcDisplay->presentOrValidate(&numTypes, &numRequests, &outPresentFence , &state);
if (!hasChangesError(error)) {
RETURN_IF_HWC_ERROR_FOR("presentOrValidate", error, displayId, UNKNOWN_ERROR);
}
if (state == 1) { //Present Succeeded.
// present成功,数据直接提交给了hwc
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;
return NO_ERROR;
}
// Present failed but Validate ran.
} else {
// 这个分支走不到
error = hwcDisplay->validate(&numTypes, &numRequests);
}
// 接收hwc过来的change,对于device合成不走,GPU合成走的逻辑,这个后续GPU合成专门分析
...
prepareFrame 的作用是根据hwc的能力选择合成方式,如果是device合成则直接走hwc present上屏,如果是GPU合成后面则走hwc validate,然后根据hwc过来的变化改变layer的合成方式。用另外一种方式表达就是首先将合成策略给HWC看是否接受,然后如果有变化就将变化应用于layer
3. 5 Output::finishFrame
cpp
文件: frameworks/native/services/surfaceflinger/CompositionEngine/src/Output.cpp
void Output::finishFrame(const compositionengine::CompositionRefreshArgs& refreshArgs) {
ATRACE_CALL();
ALOGV(__FUNCTION__);
if (!getState().isEnabled) {
return;
}
// Repaint the framebuffer (if needed), getting the optional fence for when
// the composition completes.
// 主要针对GPU合成的逻辑
auto optReadyFence = composeSurfaces(Region::INVALID_REGION, refreshArgs);
// device合成直接return
if (!optReadyFence) {
return;
}
// swap buffers (presentation)
mRenderSurface->queueBuffer(std::move(*optReadyFence));
}
composeSurface的主要核心逻辑是针对GPU合成,对于device合成,则直接return了。
3.6 Output::postFramebuffer
这块的核心逻辑主要是对于device合成设置release fence,GPU合成需要present给hwc。我们通过代码来看下:
cpp
文件:frameworks/native/services/surfaceflinger/CompositionEngine/src/Output.cpp
void Output::postFramebuffer() {
...
// device合成获取release fence
auto frame = presentAndGetFrameFences();
mRenderSurface->onPresentDisplayCompleted();
for (auto* layer : getOutputLayersOrderedByZ()) {
sp<Fence> releaseFence = Fence::NO_FENCE;
if (auto hwcLayer = layer->getHwcLayer()) {
if (auto f = frame.layerFences.find(hwcLayer); f != frame.layerFences.end()) {
releaseFence = f->second;
}
}
if (outputState.usesClientComposition) {
releaseFence =
Fence::merge("LayerRelease", releaseFence, frame.clientTargetAcquireFence);
}
// 将releasefence放到mslot里面,这个是dequeueBuffer等的fence
layer->getLayerFE().onLayerDisplayed(releaseFence);
}
...
}
文件:frameworks/native/services/surfaceflinger/DisplayHardware/HWComposer.cpp
status_t HWComposer::presentAndGetReleaseFences(DisplayId displayId) {
ATRACE_CALL();
RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
auto& displayData = mDisplayData[displayId];
auto& hwcDisplay = displayData.hwcDisplay;
// device合成直接return
if (displayData.validateWasSkipped) {
// explicitly flush all pending commands
auto error = static_cast<hal::Error>(mComposer->executeCommands());
RETURN_IF_HWC_ERROR_FOR("executeCommands", error, displayId, UNKNOWN_ERROR);
RETURN_IF_HWC_ERROR_FOR("present", displayData.presentError, displayId, UNKNOWN_ERROR);
return NO_ERROR;
}
//GPU 合成走present
auto error = hwcDisplay->present(&displayData.lastPresentFence);
RETURN_IF_HWC_ERROR_FOR("present", error, displayId, UNKNOWN_ERROR);
std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
error = hwcDisplay->getReleaseFences(&releaseFences);
RETURN_IF_HWC_ERROR_FOR("getReleaseFences", error, displayId, UNKNOWN_ERROR);
displayData.releaseFences = std::move(releaseFences);
return NO_ERROR;
}
3.6 postComposition
cpp
文件: frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::postComposition()
{
ATRACE_CALL();
ALOGV("postComposition");
nsecs_t dequeueReadyTime = systemTime();
// release Bufferqueuelayer
for (auto& layer : mLayersWithQueuedFrames) {
layer->releasePendingBuffer(dequeueReadyTime);
}
...
// mPreviousPresentFences[0]是这一帧的present fence,mPreviousPresentFences[1]是上一帧的present fence
mPreviousPresentFences[1] = mPreviousPresentFences[0];
mPreviousPresentFences[0] =
display ? getHwComposer().getPresentFence(*display->getId()) : Fence::NO_FENCE;
...
// 这个有关vsync,是校验presentfence释放的时间戳
if (display && display->isPrimary() && display->getPowerMode() == hal::PowerMode::ON &&
presentFenceTime->isValid()) {
mScheduler->addPresentFence(presentFenceTime);
}
....
}
postComposition的作用就是释放上一帧显示的Buffer,然后重新设置当前帧的present fence,以及根据presentfence时间戳判断是否重新打开HW Vsync和软件Vsync进行校准。至此,SurfaceFlinger刷新的主体函数分析完了,可以看出来,如果是走device合成,SurfaceFlinger是直接把layer信息提交给hwc,由hwc去合成.
写在最后
好了今天的博客Android下SF合成流程重学习之Refresh流程就到这里了。总之,青山不改绿水长流先到这里了。如果本博客对你有所帮助,麻烦关注或者点个赞,如果觉得很烂也可以踩一脚!谢谢各位了!!