Android SurfaceFlinger——合成预测与状态写入(四十二)

发布于:2024-07-31 ⋅ 阅读:(129) ⋅ 点赞:(0)

        前一篇文章我们介绍了 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() 重置脏区的函数,在上一篇文章中更新色彩配置时也调用了该函数。


网站公告

今日签到

点亮在社区的每一天
去签到