Android SurfaceFlinger——SF图层合成(四十一)

        上一节我们简单介绍了 SurfaceFlinger 中的图层预的流程,这里我们继续往下看,SurfaceFlinger 的真正核心——图层合成。

  • output->present:进行 Layer 合成。

一、 图层合成

1、Output.cpp

源码位置:/frameworks/native/services/surfaceflinger/CompositionEngine/src/Output.cpp

present

void Output::present(const compositionengine::CompositionRefreshArgs& refreshArgs) {
    ATRACE_CALL();
    ALOGV(__FUNCTION__);

    // 1.更新输出设备的色彩配置文件
    updateColorProfile(refreshArgs);
    // 2.更新与合成相关的状态
    updateCompositionState(refreshArgs);
    // 3.计划合成帧图层
    planComposition();
    // 4.写入合成状态
    writeCompositionState(refreshArgs);
    // 5.设置颜色矩阵
    setColorTransform(refreshArgs);
    // 6.开始帧
    beginFrame();

    // 准备帧
    GpuCompositionResult result;
    const bool predictCompositionStrategy = canPredictCompositionStrategy(refreshArgs);
    // 根据是否可以预测合成策略,选择同步或异步的方式准备帧。
    if (predictCompositionStrategy) {
        // 7.准备帧数据以进行显示(异步方式)
        result = prepareFrameAsync(refreshArgs);
    } else {
        // 8.准备帧数据以进行显示(同步方式)
        prepareFrame();
    }

    // 9.处理显示输出设备的可选重绘闪烁
    devOptRepaintFlash(refreshArgs);
    // 10.结束帧
    finishFrame(refreshArgs, std::move(result));
    // 11.将渲染完成的帧缓冲发布到显示设备
    postFramebuffer();
    // 12.进行渲染缓存设置
    renderCachedSets(refreshArgs);
}

         整个 present() 函数流程涵盖了从接收刷新请求、更新状态、规划合成、准备帧、完成帧到最终发布的完整过程,是图形渲染管线中的关键环节。

二、合成解析

1、更新色彩配置

updateColorProfile

void Output::updateColorProfile(const compositionengine::CompositionRefreshArgs& refreshArgs) {
    setColorProfile(pickColorProfile(refreshArgs));
}

setColorProfile 

void Output::setColorProfile(const ColorProfile& colorProfile) {
    ui::Dataspace targetDataspace =
            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();
}

setBufferDataspace:设置缓存数据空间。

dirtyEntireOutput:重置脏区。

setBufferDataspace

源码位置:/frameworks/native/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp

void RenderSurface::setBufferDataspace(ui::Dataspace dataspace) {
    // 调用原生API。设置窗口的缓冲数据空间
    native_window_set_buffers_data_space(mNativeWindow.get(), static_cast<android_dataspace>(dataspace));
}

        该函数设置与该渲染表面关联的原生窗口(mNativeWindow)的数据空间属性。数据空间(Dataspace)在图形和视频处理领域指的是色彩空间和色域的规范,它决定了像素值如何映射到实际颜色上。 

dirtyEntireOutput
void Output::dirtyEntireOutput() {
    // 获取输出状态引用。outputState是一个存储当前输出设备状态的对象
    auto& outputState = editState();
    // 设置脏区为整个显示区域
    outputState.dirtyRegion.set(outputState.displaySpace.getBoundsAsRect());
}

outputState.dirtyRegion:设置为整个显示空间的边界矩形。

getBoundsAsRect:返回一个表示显示空间边界范围的矩形对象。

set:用于将 dirtyRegion 的值更新为此矩形,表示整个输出设备的显示区域都已变为“脏”。

        该函数的作用是标记整个输出设备的显示区域为“脏”(dirty),意味着这一区域的所有内容都需要被重新绘制或更新。在图形渲染和用户界面管理中,“脏”区域是指那些自上次渲染以来发生了变化,需要重新绘制的屏幕区域。

Region.set

源码位置:/frameworks/native/libs/ui/Region.cpp

void Region::set(const Rect& r)
{
    // 清空当前区域
    mStorage.clear();
    // 添加新的矩形
    mStorage.push_back(r);
}

        该函数的主要目的是快速地重置或初始化 Region 对象,Region 通常用来表示一个或多个矩形区域的集合,用于描述如窗口、控件的可见区域、需要更新的屏幕区域等。 

2、更新合成状态

updateCompositionState

void Output::updateCompositionState(const compositionengine::CompositionRefreshArgs& refreshArgs) {
    ……
    // 检查输出设备是否启用
    if (!getState().isEnabled) {
        return;
    }

    // 查找请求背景模糊的图层
    mLayerRequestingBackgroundBlur = findLayerRequestingBackgroundComposition();
    // 如果找到了请求背景模糊的图层,设置强制客户端合成标志
    bool forceClientComposition = mLayerRequestingBackgroundBlur != nullptr;

    // 遍历所有按Z轴顺序排列的图层并更新图层的合成状态
    for (auto* layer : getOutputLayersOrderedByZ()) {
        layer->updateCompositionState(refreshArgs.updatingGeometryThisFrame, refreshArgs.devOptForceClientComposition ||
                forceClientComposition, refreshArgs.internalDisplayRotationFlags);

        if (mLayerRequestingBackgroundBlur == layer) {
            forceClientComposition = false;
        }
    }
}

        该函数主要职责是根据传入的 CompositionRefreshArgs 更新输出设备上所有图层的合成状态。在图形渲染和合成引擎中,合成状态包含了图层如何被组合和渲染到屏幕上的信息,包括位置、尺寸、可见性、混合模式等。这里最终调用 OutputLayer 中的对应函数继续更新合成状态。

OutputLayer.cpp

源码位置:/frameworks/native/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp

void OutputLayer::updateCompositionState(bool includeGeometry, bool forceClientComposition,
        ui::Transform::RotationFlags internalDisplayRotationFlags) {
    // 获取图层前端状态
    const auto* layerFEState = getLayerFE().getCompositionState();
    if (!layerFEState) {
        return;
    }

    const auto& outputState = getOutput().getState();
    const auto& profile = *getOutput().getDisplayColorProfile();
    auto& state = editState();

    // 更新几何状态
    if (includeGeometry) {
        // 清除forceClientComposition标志,准备重新评估
        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;
        }
    }

    // 根据图层前端状态和输出设备状态,决定图层的数据空间
    state.dataspace = layerFEState->isColorspaceAgnostic && outputState.targetDataspace != ui::Dataspace::UNKNOWN
            ? outputState.targetDataspace : layerFEState->dataspace;

    // 根据设备配置,调整数据空间传输特性
    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);
    }

    // 亮度和白点调整
    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;
    }

    // 合成策略决策
    if (layerFEState->forceClientComposition || !profile.isDataspaceSupported(state.dataspace) ||
        forceClientComposition) {
        state.forceClientComposition = true;
    }
}

        这里通过综合考虑图层属性、输出设备状态和系统配置,动态调整图层的合成策略和显示参数,确保图层内容在各种条件下都能得到正确的呈现。包括了处理复杂的色彩管理、亮度调整和合成优化,对于提升图形渲染质量和效率具有重要作用。

  • 11
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

c小旭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值