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