前一篇文章我们介绍了 SurfaceFlinger 图层合成的整体流程,并对前两个流程更新色彩配置和更新合成状态进行了介绍,这里我们接着解析下面的流程。
- 1.更新输出设备的色彩配置文件
- 2.更新与合成相关的状态
- 3.计划合成帧图层
- 4.写入合成状态
- 5.设置颜色矩阵
- 6.开始帧
- 7.准备帧数据以进行显示(异步方式)
- 8.准备帧数据以进行显示(同步方式)
- 9.处理显示输出设备的可选重绘闪烁
- 10.结束帧
- 11.将渲染完成的帧缓冲发布到显示设备
- 12.进行渲染缓存设置
一、计划合成预测
1、Output.cpp
源码位置:/frameworks/native/services/surfaceflinger/CompositionEngine/src/Output.cpp
planComposition
void Output::planComposition() {
// 检查规划器和输出状态
if (!mPlanner || !getState().isEnabled) {
return;
}
……
// 调用规划器进行合成规划
mPlanner->plan(getOutputLayersOrderedByZ());
}
该函数主要职责是调用规划器(mPlanner)来计划输出设备上所有图层的合成方案。
2、Planner.cpp
源码位置:/frameworks/native/services/surfaceflinger/CompositionEngine/src/planner/Planner.cpp
plan
void Planner::plan(compositionengine::Output::OutputLayersEnumerator<compositionengine::Output>&& layers) {
ATRACE_CALL();
// 用来存储上一帧存在的图层ID
std::unordered_set<LayerId> removedLayers;
removedLayers.reserve(mPreviousLayers.size());
// 将mPreviousLayers中所有图层的ID提取并插入到removedLayers集合中
std::transform(mPreviousLayers.begin(), mPreviousLayers.end(),
std::inserter(removedLayers, removedLayers.begin()),
[](const auto& layer) { return layer.first; });
std::vector<LayerId> currentLayerIds;
// 遍历当前帧的所有图层
for (auto layer : layers) {
LayerId id = layer->getLayerFE().getSequence();
// 检查每个图层是否在mPreviousLayers中存在
if (const auto layerEntry = mPreviousLayers.find(id); layerEntry != mPreviousLayers.end()) {
// 更新图层状态
LayerState& state = layerEntry->second;
……
} else { // 图层是新加入的
// 创建一个新的LayerState实例并将其添加到mPreviousLayers中
LayerState state(layer);
ALOGV("Added layer %s", state.getName().c_str());
mPreviousLayers.emplace(std::make_pair(id, std::move(state)));
}
// 将当前帧的图层ID添加到currentLayerIds中
currentLayerIds.emplace_back(id);
// 从removedLayers集合中移除当前帧存在的图层ID
if (const auto found = removedLayers.find(id); found != removedLayers.end()) {
removedLayers.erase(found);
}
}
// 清空并重新准备mCurrentLayers容器
mCurrentLayers.clear();
mCurrentLayers.reserve(currentLayerIds.size());
// 将图层ID转换成LayerState
std::transform(currentLayerIds.cbegin(), currentLayerIds.cend(), std::back_inserter(mCurrentLayers), [this](LayerId id) {
LayerState* state = &mPreviousLayers.at(id);
state->getOutputLayer()->editState().overrideInfo = {};
return state;
});
// 计算当前图层状态的非缓冲区哈希值
const NonBufferHash hash = getNonBufferHash(mCurrentLayers);
// 图层扁平化处理
mFlattenedHash = mFlattener.flattenLayers(mCurrentLayers, hash, std::chrono::steady_clock::now());
const bool layersWereFlattened = hash != mFlattenedHash;
……
if (mPredictorEnabled) {
// 根据当前图层状态预测最有效的合成计划
mPredictedPlan = mPredictor.getPredictedPlan(layersWereFlattened
? std::vector<const LayerState*>() : mCurrentLayers, mFlattenedHash);
……
}
// 清理不再存在的图层状态.
for (LayerId removedLayer : removedLayers) {
if (const auto layerEntry = mPreviousLayers.find(removedLayer);
layerEntry != mPreviousLayers.end()) {
const auto& [id, state] = *layerEntry;
ALOGV("Removed layer %s", state.getName().c_str());
mPreviousLayers.erase(removedLayer);
}
}
}
该函数是在每次合成前,对图层状态进行跟踪和更新,然后基于当前图层状态和历史信息预测或计算最有效的合成计划。
二、写入合成状态
1、Output.cpp
writeCompositionState
void Output::writeCompositionState(const compositionengine::CompositionRefreshArgs& refreshArgs) {
……
// 判断输出状态是否启用
if (!getState().isEnabled) {
return;
}
// 更新呈现时间
editState().earliestPresentTime = refreshArgs.earliestPresentTime;
editState().previousPresentFence = refreshArgs.previousPresentFence;
editState().expectedPresentTime = refreshArgs.expectedPresentTime;
// 用于跟踪“穿透”层
compositionengine::OutputLayer* peekThroughLayer = nullptr;
// 用于存储前一个覆盖缓冲区
sp<GraphicBuffer> previousOverride = nullptr;
// 控制是否包含几何信息
bool includeGeometry = refreshArgs.updatingGeometryThisFrame;
// 用于排序的Z轴位置
uint32_t z = 0;
// 标记是否覆盖Z轴位置
bool overrideZ = false;
// 用于计算输出层的哈希值
uint64_t outputLayerHash = 0;
// 遍历按Z轴顺序排列的所有输出层
for (auto* layer : getOutputLayersOrderedByZ()) {
// 检查是否已经处理过
if (layer == peekThroughLayer) {
// 该层已经在之前的处理中被提前绘制了
peekThroughLayer = nullptr;
continue;
}
bool skipLayer = false;
const auto& overrideInfo = layer->getState().overrideInfo;
// 检查层是否有覆盖信息
if (overrideInfo.buffer != nullptr) {
// 检查是否与前一个覆盖缓冲区相同
if (previousOverride && overrideInfo.buffer->getBuffer() == previousOverride) {
// 如果相同,则跳过此层,避免重复绘制
skipLayer = true;
} else {
// 第一个带有该覆盖缓冲区的层
if (overrideInfo.peekThroughLayer) {
// 处理“穿透”层
peekThroughLayer = overrideInfo.peekThroughLayer;
overrideZ = true;
includeGeometry = true;
constexpr bool isPeekingThrough = true;
// 更新硬件复合器(Hardware Composer)的状态
peekThroughLayer->writeStateToHWC(includeGeometry, false, z++, overrideZ, isPeekingThrough);
// 更新outputLayerHash
outputLayerHash ^= android::hashCombine(reinterpret_cast<uint64_t>
(&peekThroughLayer->getLayerFE()), z, includeGeometry, overrideZ,
isPeekingThrough, peekThroughLayer->requiresClientComposition());
}
previousOverride = overrideInfo.buffer->getBuffer();
}
}
// 每次处理完一个层后,都会根据层的信息更新outputLayerHash
constexpr bool isPeekingThrough = 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());
}
}
// 将计算得到的outputLayerHash赋值给editState().outputLayerHash,完成整个状态更新过程。
editState().outputLayerHash = outputLayerHash;
}
该函数的主要功能是根据给定的 CompositionRefreshArgs 参数更新输出层的状态,包括设置呈现时间、处理覆盖缓冲区、以及计算输出层的哈希值。
2、OutputLayer.cpp
源码位置:/frameworks/native/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
void OutputLayer::writeStateToHWC(bool includeGeometry, bool skipLayer, uint32_t z,
bool zIsOverridden, bool isPeekingThrough) {
// 检查HWC接口是否存在
const auto& state = getState();
if (!state.hwc) {
return;
}
// 获取HWC层句柄
auto& hwcLayer = (*state.hwc).hwcLayer;
if (!hwcLayer) {
……
return;
}
// 获取独立于输出的层状态
const auto* outputIndependentState = getLayerFE().getCompositionState();
if (!outputIndependentState) {
return;
}
// 确定渲染类型
auto requestedCompositionType = outputIndependentState->compositionType;
if (requestedCompositionType == Composition::SOLID_COLOR && state.overrideInfo.buffer) {
requestedCompositionType = Composition::DEVICE;
}
// 判断是否需要更新状态
const bool isOverridden = state.overrideInfo.buffer != nullptr || isPeekingThrough || zIsOverridden;
const bool prevOverridden = state.hwc->stateOverridden;
if (isOverridden || prevOverridden || skipLayer || includeGeometry) {
// 更新几何状态
writeOutputDependentGeometryStateToHWC(hwcLayer.get(), requestedCompositionType, z);
writeOutputIndependentGeometryStateToHWC(hwcLayer.get(), *outputIndependentState, skipLayer);
}
// 更新每帧状态
writeOutputDependentPerFrameStateToHWC(hwcLayer.get());
writeOutputIndependentPerFrameStateToHWC(hwcLayer.get(), *outputIndependentState, requestedCompositionType, skipLayer);
// 更新渲染类型
writeCompositionTypeToHWC(hwcLayer.get(), requestedCompositionType, isPeekingThrough, skipLayer);
// 处理纯色渲染
if (requestedCompositionType == Composition::SOLID_COLOR) {
writeSolidColorStateToHWC(hwcLayer.get(), *outputIndependentState);
}
// 更新状态标志
editState().hwc->stateOverridden = isOverridden;
editState().hwc->layerSkipped = skipLayer;
}
该函数负责将当前 OutputLayer 的状态写入到硬件复合器 HWC 中,以便于 HWC 能够正确地渲染和合成当前层。
三、设置颜色矩阵
1、Output.cpp
setColorTransform
void Output::setColorTransform(const compositionengine::CompositionRefreshArgs& args) {
// 检查颜色变换矩阵是否需要更新
auto& colorTransformMatrix = editState().colorTransformMatrix;
if (!args.colorTransformMatrix || colorTransformMatrix == args.colorTransformMatrix) {
return;
}
// 更新颜色变换矩阵
colorTransformMatrix = *args.colorTransformMatrix;
// 标记输出为脏状态,重新渲染整个输出
dirtyEntireOutput();
}
该函数的作用是更新 Output 对象的颜色变换矩阵。可以看到最终也调用了 dirtyEntireOutput() 重置脏区的函数,在上一篇文章中更新色彩配置时也调用了该函数。