前言
本文基于Android 14源码分析整理
合成是指对多个图层合成到一个最终图层上,并同步给硬件屏幕进行呈现的这个过程。整个过程软硬件协同参与:
- surfaceflinger:负责图层的管理,包括图层状态管理、GraphicBuffer管理、图层位置、层级、区域的计算等;
- GPU:GPU负责内容的绘制和合成,可以快速执行复杂的图形计算任务;
- Hardware composer: 硬件合成器,为了减轻CPU和GPU压力,通过专门的硬件图形处理单元,来提升图形合成效率和系统执行效率;
根据合成方式的不同,在实际执行过程中,可分为三种情况:
- GPU合成(Client合成):使用GPU对图层进行合成,可处理复杂的图形任务,灵活性强,但功耗高,同时处理复杂图形任务时,可能会带来性能问题;
- DPU合成(Device合成):使用HWC对图层进行合成,减轻CPU和GPU负载,合成效率高、功耗低,但复杂的图形任务无法实现,一般只支持简单的图形合成任务;
- Mixed合成:表示在一次合成过程中,GPU合成和DPU合成都有参与,有些图层通过GPU合成,剩余图层则通过DPU合成。
Client合成和Device合成优缺点如下:
优点 | 缺点 | |
---|---|---|
Client合成 | 1. 计算力强:能处理处理复杂的图形任务和大量图层; 2. 特效强:能实现高级特效,入模糊、阴影、辉光等; 3. 灵活性强:不强依赖硬件,跨平台(shader自定义效果); | 1. 性能影响:大量的GPU计算会影响其他任务的调度; 2. 功耗影响:GPU合成会消耗更多的功耗; |
Device合成 | 1. 性能强:通过单独的硬件处理单元,减轻CPU/GPU压力,提升系统整体性能; 2. 高效地处理多个图层的合成,提供较低的延迟和更高的帧率; 3. 功耗低:相比软件合成,能更有效降低功耗; | 1. 灵活性差:不同设备可能使用不同的HWC,对合成效果有影响; 2. 合成类型单一:受硬件设计的限制,无法支持所有复杂的图形效果; 3. 图层数量受限:一般直支持图层最大个数有限; |
合成过程可以说是surfaceflinger进程的主线任务,在这条任务线上,几乎贯穿了所有的支线任务(Layer创建/销毁、层级更新、GraphicBuffer锁定/释放、屏幕管理......)
在这个过程中,Layer和Display(Output)作为合成工作和于硬件屏幕交互的元数据,将图层数据传递给HWC/GPU进行处理后完成显示。
从本篇文章开始,将通过一系列文档对合成流程进行详细的梳理分析,本篇将首先会对整个合成过程中的关键操作进行基础性的介绍。
当surfaceflinger进程由于收到新内容而被VSYNC信号唤醒后,便执行合成操作。整个合成操作可分为两个大阶段:
- 提交阶段:主要负责Transaction更新、Layer属性的更新和准备工作;
- 合成阶段:当提交阶段导致显示内容更改时,进入合成阶段执行合成操作。会将图层信息更新给HWC完成内容的更新与显示。
全部流程如下图所示:
一、提交阶段
在提交阶段,会将收到的Transaction中携带的各类数据进行应用,更新Layer的相关属性。在提交阶段,主要还是以Layer为核心进行操作。
SurfaceFlinger中收到VSYNC信号后,首先是执行commit()
方法,对Transaction队列进行过滤提交:
cpp
// frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
bool SurfaceFlinger::commit(TimePoint frameTime, VsyncId vsyncId, TimePoint expectedVsyncTime)
FTL_FAKE_GUARD(kMainThreadContext) {
......
{
frontend::Update updates;
// 1. 刷新提交事件
if (flushTransactions) {
updates = flushLifecycleUpdates();
}
bool transactionsAreEmpty;
// 2. 更新LayerSnapshot、提交Transaction携带参数
if (mLegacyFrontEndEnabled) {
mustComposite |= updateLayerSnapshotsLegacy(vsyncId, updates, flushTransactions,
transactionsAreEmpty);
}
......
if (transactionFlushNeeded()) {
setTransactionFlags(eTransactionFlushNeeded);
}
......
}
......
return mustComposite && CC_LIKELY(mBootStage != BootStage::BOOTLOADER);
}
这里对commit()方法进行了大量精简,只关注合成过程中针对Layer处理最为核心的步骤:
-
执行
flushLifecycleUpdates()
方法刷新提交事件;- 过滤Transaction队列,收集满足此次提交条件的Transaction;
- 收集新建Layer列表;
- 收集待销毁Layer列表;
-
执行
updateLayerSnapshotsLegacy()
方法应用并提交Transaction携带参数;- 提交Mirror Display;
- 提交新创建Layer;
- 应用Transaction携带参数;
- 提交Transaction;
- 执行latch Buffer操作;
- 更新Layer几何属性。
1.1、刷新提交事件
业务进程在执行完成Transaction::apply()
操作后,会将Transaction保存在队列mPendingTransactionQueues
中,这步操作在binder线程完成,然后在提交阶段,会遍历该队列,选择符合此次提交的Transaction参与后续合成过程。
Transaction可以支持设置一些具体的条件来指定它的提交时机,比如可以指定期望合成时间(desiredPresentTime)、Buffer barrier、Fence信号等条件,满足后才会允许其参与到合成过程。
完成过滤后,会将符合条件的Transaction列表保持在frontend::Update中参与后续流程。
此外,在这里还会将新建Layer列表和销毁LayerHandle列表也保存在frontend::Update对象中,为后续进行逻辑结构的更新做准备。
关于Layer创建和销毁流程,见:
1.2、应用并提交Transaction
完成Transaction的过滤、填充完成frontend::Update对象后,将开始执行updateLayerSnapshotsLegacy()
方法应用并提交Transaction携带参数。
1.2.1、提交Mirror Display
通过commitMirrorDisplays()
方法,对创建的镜像虚拟屏进行LayerTree的构建。这个过程中,会根据创建时指定的rootLayer,遍历其所有子Layer,并创建对应的镜像Layer。
在Android 14中,在镜像时会创建一个"MirrorRoot" Layer,并对所有被镜像Layer拷贝创建新的Layer:
cpp
// frameworks/native/services/surfaceflinger/Layer.cpp
void Layer::updateClonedChildren(const sp<Layer>& mirrorRoot,
std::map<sp<Layer>, sp<Layer>>& clonedLayersMap) {
......
sp<Layer> clonedFrom = getClonedFrom();
// 对被镜像Layer的所有子Layer进行拷贝,生成新的Layer
for (sp<Layer>& child : clonedFrom->mDrawingChildren) {
sp<Layer> clonedChild = clonedLayersMap[child];
if (clonedChild == nullptr) {
clonedChild = child->createClone(mirrorRoot->getSequence());
clonedLayersMap[child] = clonedChild;
}
addChildToDrawing(clonedChild);
clonedChild->updateClonedChildren(mirrorRoot, clonedLayersMap);
}
}
而在Android 15上开始,对Layer结构进行了优化,通过图结构的方式,不再拷贝创建新Layer对象,而是直接创建一个Mirror Root节点后建立镜像关系:
cpp
// frameworks/native/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp
void LayerHierarchyBuilder::updateMirrorLayer(RequestedLayerState* layer) {
LayerHierarchy* hierarchy = getHierarchyFromId(layer->id);
......
// layer->mirrorIds中保存整个LayerStack的镜像layer
for (uint32_t mirrorId : layer->mirrorIds) {
// 将被镜像layer对应添加到hierarchy的mChildren列表中,关系为Mirror
hierarchy->addChild(getHierarchyFromId(mirrorId), LayerHierarchy::Variant::Mirror);
}
if (FlagManager::getInstance().detached_mirror()) {
// layer->layerIdToMirror表示镜像单个layer
// 将被镜像layer对应添加到hierarchy的mChildren列表中,关系为Detached_Mirror
if (layer->layerIdToMirror != UNASSIGNED_LAYER_ID) {
hierarchy->addChild(getHierarchyFromId(layer->layerIdToMirror),
LayerHierarchy::Variant::Detached_Mirror);
}
}
}
1.2.2、提交新创建Layer
通过commitCreatedLayers()
方法,将会对新创建的Layer进行逻辑结构的设置,包括为其设置父Layer和存储位置等。
1.2.3、应用Transaction携带参数
从applyTransactions()
方法开始,将会对已筛选的Transaction进行应用。
在SurfaceComposerClient中,客户端进程将更新属性放在了两个结构体中:
- DisplayState:保存更新给surfaceflinger的Display信息;
- ComposerState:保存更新给surfaceflinger的Layer信息;
在该方法中,会遍历以上结构体,并通过setDisplayStateLocked()
和setClientStateLocked()
方法分别为对应的Display和Layer进行属性更新,将Transaction中的参数赋给Display和Layer。
1.2.4、提交Transaction
从commitTransactions()
方法开始,会根据transactionFlags标记,进行SurfaceFlinger提交状态、Layer提交状态等全局状态的更新,这一步是整个提交阶段中核心的一步,主要操作包括:
- 处理Display更新:包括更新、添加、移除对应的DisplayDevice以相关组件;
- 处理Layer更新:包括Layer的mDrawingState、mDrawingParent、mDrawingChildren更新、已销毁Layer Offscreen列表更新;
- 更新
mDrawingState
:代表SurfaceFlinger类中当前全局状态;
执行完成这一步后,SurfaceFlinger类和Layer中所有的状态都已经完成更新。
1.1.3、latchBuffers操作
SurfaceFlinger::latchBuffers()
方法开始,将会对Layer进行Buffer的锁存操作。首先会收集有帧更新的Layer,将它们放在mLayersWithQueuedFrames
列表中,然后对这个列表中的元素分别进行Buffer锁存操作,具体就是对Layer::mBufferInfo
进行更新,并在后续流程中,将Buffer信息传递给HWC进行进一步合成。
从trace上看,当完成latchBuffers操作后,"Pending Buffer"的个数将会减一:
1.1.4、更新Layer的几何参数
updateLayerGeometry()
方法中,会对当前所有Layer按照层级关系进行几何属性的计算和更新根据Layer层级。这里会更新Layer的以下几个属性:
- mEffectiveTransform:表示该Layer的LayerStack空间变换矩阵,由Parent 变换矩阵对象乘以Layer自己的变换矩阵对象获得,用于将Layer空间图形变换到LayerStack空间;
- mBounds:表示经过指定的Crop和Parent bound裁剪后的区域,但还未经过变换,也是当前Layer空间内的显示区域;
这两值可以在dump信息中看到:
完成提交操作后,Transaction中携带的参数全部完成应用,同时Display、Layer中的状态也全部更新完成,根据提交操作的返回结果,将决定是否进行合成操作。
二、合成阶段(composite)
从SurfaceFlinger::composite()
方法开始,将进入合成阶段,这个过程中,Layer和Composition::Display(即Output)作为元数据,根据设置的所有属性(位置、颜色、内容、层级),经过多层处理,将Layer内容最终呈现在屏幕上。
在合成阶段,图层数据会从Layer到LayerFE、再到OutputLayer和HWC::Layer,并流向HW Composer。图层属性的封装类型也会从LayerSnapShot
到OutputLayerCompositionState
,对应不同的图层类型。同时,会以Output为基本单位,对每个屏幕执行合成。合成方式的选择也是在这个过程中确定。
合成阶段核心步骤拆解如下:
-
填充CompositionRefreshArgs属性;
-
更新LayerSnapshot并转移所有权给LayerFE;
-
Output中执行准备操作(prepare);
- 构建参与合成的Layer栈;
- 执行uncacheBuffer操作;
-
Output中执行准备操作(prepare);
-
Output中执行合成操作(present);
-
合成后的处理(将LayerSnapshot转移回Layer)。
2.1、填充CompositionRefreshArgs属性
CompositionRefreshArgs
表示用于指定、描述合成操作的一个合成参数,其中保存了需要合成的屏幕(Output)、Layer、以及其他共性特征,在SurfaceFlinger类中完成填充后,传递给CompositionEngine类后根据CompositionRefreshArgs中的数据执行后续操作。
cpp
// frameworks/native/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h
struct CompositionRefreshArgs {
// std::vector<std::shared_ptr<compositionengine::Output>>类型,
// 用于保存所有compositionengine::Output对象
Outputs outputs;
// std::vector<sp<compositionengine::LayerFE>>类型,
// 用于保存所有可能可见的LayerFE,按照层级升序顺序排列
Layers layers;
// 所有进行了latchBuffer的LayerFE列表
Layers layersWithQueuedFrames;
// uncached buffer id,用于更新buffer cache
std::vector<uint64_t> bufferIdsToUncache;
// 用于控制如何为Output选择Color mode,有三个值:
// kManaged = 0,
// kUnmanaged = 1,
// kEnhanced = 2,
OutputColorSetting outputColorSetting{OutputColorSetting::kEnhanced};
// 色彩空间相关
ui::Dataspace colorSpaceAgnosticDataspace{ui::Dataspace::UNKNOWN};
// 通过属性persist.sys.sf.color_mod强制设置的色彩空间,ui::ColorMode::NATIVE表示未设置
ui::ColorMode forceOutputColorMode{ui::ColorMode::NATIVE};
// 当前屏幕旋转方向
ui::Transform::RotationFlags internalDisplayRotationFlags{ui::Transform::ROT_0};
// 是否要在该帧中更新Output各区域,该值由SF::mVisibleRegionsDirty变量值决定
bool updatingOutputGeometryThisFrame{false};
// 是否需要在该帧中更新Layer显示区域,与上一个变量为充分不必要关系
bool updatingGeometryThisFrame{false};
// Color变换矩阵,只有当色彩矩阵发生变化后才会更新
std::optional<mat4> colorTransformMatrix;
// true表示强制使用GPU合成,如开发者选项中的"停用HW叠加层"开启时
bool devOptForceClientComposition{false};
// 是否开启开发者选项中"显示Surface更新"
std::optional<std::chrono::microseconds> devOptFlashDirtyRegionsDelay;
// 最早present时间,将当前命令发送给HAL的最早时间,跟Vsync period相关
std::optional<std::chrono::steady_clock::time_point> earliestPresentTime;
// 下一帧的期望时间
nsecs_t expectedPresentTime{0};
// 该帧执行的时间
std::optional<std::chrono::steady_clock::time_point> scheduledFrameTime;
std::vector<BorderRenderInfo> borderInfoList;
// 是否有注册可信监听
bool hasTrustedPresentationListener = false;
};
2.2、更新LayerSnapshot并转移所有权给LayerFE
Layer在创建时会初始化一个LayerSnapshot对象,表示该Layer的"快照",用来保存合成过程中的相关数据,而且LayerSnapshot可以在Layer跟LayerFE之间移动,在合成过程中,会将LayerSnapshot转移给LayerFE参与合成,完成后转移会Layer中。
在moveSnapshotsToCompositionArgs()
方法中,会先对LayerSnapshot进行更新,包括各类几何属性、合成方式、色彩属性.......等。
完成更新后,将其转移给LayerFE,同时将LayerFE对象放置到refreshArgs.layers
中:
cpp
// frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
// 更新LayerSnapshot
layer->updateSnapshot(refreshArgs.updatingGeometryThisFrame);
// 转移给LayerFE
layerFE->mSnapshot = layer->stealLayerSnapshot();
// 将LayerFE放在refreshArgs.layers中
refreshArgs.layers.push_back(layerFE);
完成这一步操作后,接下来的流程中,将通过CompositionEngine::present()
方法,对每个Output单独进行处理:
cpp
// frameworks/native/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp
void CompositionEngine::present(CompositionRefreshArgs& args) {
{
LayerFESet latchedLayers;
// 准备OuputLayer过程
for (const auto& output : args.outputs) {
output->prepare(args, latchedLayers);
}
}
// 呈现过程
for (const auto& output : args.outputs) {
output->present(args);
}
}
下面进入Output中,看下prepare和present分别做了哪些工作。
2.3、Output中执行准备操作(prepare)
这个方法中,将开始进入合成前的准备阶段:
cpp
// frameworks/native/services/surfaceflinger/CompositionEngine/src/Output.cpp
void Output::prepare(const compositionengine::CompositionRefreshArgs& refreshArgs,
LayerFESet& geomSnapshots) {
.......
// 收集、构建需要参与合成的Layer栈
rebuildLayerStacks(refreshArgs, geomSnapshots);
// 进行uncache buffer操作
uncacheBuffers(refreshArgs.bufferIdsToUncache);
}
从以上方法可知,准备操作包括两部分任务:
- 收集、构建参与此次合成的Layer栈;
- 处理uncacheBuffer操作;
2.3.1、构建参与合成的Layer栈
通过Output::rebuildLayerStacks()
方法,开始构待合成Layer的Layer栈。
2.3.1.1、收集参与合成的Layer列表
添加到refreshArgs.layers
列表中的LayerFE是对当前所有的Layer进行遍历的结果,并非这里所有的LayerFE都会参与到合成过程,比如设置为隐藏不可见(通过Transaction.hide()
设置)、透明度为0、没有Buffer/Color/Blur/Shadow等时,都不会进行合成显示。
此外,也会根据LayerStack来对Output和Layer进行匹配,以确保Layer按照期望的方式合成并显示在正确的屏幕上。
2.3.1.2、计算Layer显示区域
在Layer筛选的过程中,会同步对确定参与合成的Layer进行各区域计算,如可见区域、覆盖区域、阴影区域等。
Layer筛选的过程是从高层级到底层进行的,每次计算时都会对上一层的区域取交集,以得到新的区域。
我们在dump信息中看到的区域,就是通过这里计算获得:
2.3.1.3、创建OutputLayer和HWC2::Layer
OutputLayer是图层的进一步封装,相比LayerFE更偏底一层,封装了所有的用于合成的状态属性,这些状态保存在OutputLayerCompositionState中。
HWC2::Layer则是相比OutputLayer的更进一步封装,也是surfaceflinger进程中的最后一层封装类,也是Layer合成状态流向HW Composer的最末端。它由HW Composer创建并返回,通过HWC2::Layer将surfaceflinger进程中所有合成Layer的数据传递给HW Composer HAL。
OutputLayer的创建以模板类的方式创建,创建完成后,会保存在Output::mCurrentOutputLayersOrderedByZ
列表中,后续操作,将通过OutputLayer进行。
Layer、LayerFE、OutputLayer、HWC2::Layer的递进关系如图所示:
2.3.2、执行uncacheBuffer操作
这一步是关于GraphicBuffer在Client端和sf端传递过程中的一个缓存机制处理。每个Layer申请的GraphicBuffer数量是固定且通过BufferQueue的调用进行循环使用。如果每次刷帧过程中传递GraphicBuffer对象本身,传递数据占用内存开销会很大,因此,通过GraphicBuffer的缓存机制,只有当Client端和sf端第一次使用到该GraphicBuffer时,才会传递实际GraphicBuffer对象本身,并且同时通过一个映射表缓存起来,后续再使用时,仅仅传递其buffer id即可。
当Client端缓存状态发生变化后,也需要同步到sf侧,进行uncacheBuffer的处理,从而对该GraphicBuffer的操作和Client端保持一致。
2.4、Output中执行合成操作(present)
完成准备工作后,接下来将进入合成操作,对每个OutputLayer更新OutputLayerCompositionState属性,通过HWC2::Layer传递给HW Composer,然后给HWC发送present命令,完成合成与上屏的工作。
这一步通过Output::present()
方法实现:
cpp
// frameworks/native/services/surfaceflinger/CompositionEngine/src/Output.cpp
void Output::present(const compositionengine::CompositionRefreshArgs& refreshArgs) {
// 向OutputCompositionState中设置ColorMode/Dataspace相关属性
updateColorProfile(refreshArgs);
// 向OutputCompositionState中设置其他合成状态
updateCompositionState(refreshArgs);
planComposition();
// 向HW Composer传递合成状态
writeCompositionState(refreshArgs);
setColorTransform(refreshArgs);
beginFrame();
GpuCompositionResult result;
const bool predictCompositionStrategy = canPredictCompositionStrategy(refreshArgs);
if (predictCompositionStrategy) {
// HWC异步合成
result = prepareFrameAsync();
} else {
// 向HW Composer发送校验和合成命令
prepareFrame();
}
devOptRepaintFlash(refreshArgs);
// 根据HWComposer返回结果,决定是否再进行GPU合成
finishFrame(std::move(result));
// 完成合成操作后对Framebuffer处理
postFramebuffer();
// 缓存
renderCachedSets(refreshArgs);
}
这个方法中涉及的操作量很大,核心几个任务拆解如下:
- 为所有OuptutLayer设置合成状态属性;
- 向HW Composer发送合成状态;
- 向HW Composer发送校验合成命令;
- 执行GPU合成(根据HWComposer返回结果,决定是否进行GPU合成)。
2.4.1、给OuptutLayer设置合成状态属性
每个OuputLayer的合成状态属性都是保存在OutputLayerCompositionState对象中,Output::present()
方法执行之初就会更新所有OuputLayer的OutputLayerCompositionState属性:
updateColorProfile()
中更新Color mode、dataspace等属性;updateCompositionState()
中更新其他属性。
合成方式的选择也是在这里进行,比如遍历OutputLayer寻找是否存在背景模糊的Layer,如果存在,该Layer及其底部的Layer会强制使用client合成。
2.4.2、向HW Composer发送合成状态
完成OutputLayerCompositionState的更新后,将通过HWC2::Layer把设置的所有合成状态传递给HW Composer。
这一步是通过Output::writeCompositionState()
方法开始,并陆续执行OutputLayer中的多个"write"命名开头的方法,最终通过HWC HAL定义的接口传递给HW Composer。
2.4.3、向HW Composer发送校验合成命令
接下来便是向HWC发送校验及合成命令,HWC中检查Layer状态,并决定如何进行合成。
Android 12开始,系统开始支持HWC异步合成,即将校验检查放在了单独的线程进行:
cpp
// frameworks/native/services/surfaceflinger/CompositionEngine/src/Output.cpp
GpuCompositionResult result;
// 是否支持HWC异步合成
const bool predictCompositionStrategy = canPredictCompositionStrategy(refreshArgs);
if (predictCompositionStrategy) {
result = prepareFrameAsync();
} else {
// 主线程合成
prepareFrame();
}
但由于受平台影响,目前主流平台都未使用异步合成,这里我们依然以主线程合成流程为主。
这步操作从Output::prepareFrame()
方法开始,HWC合成的全部操作基本都在这里完成:
- Step 1、 调用
presentOrValidate
方法,向HWC发送present命令,HWC中决定如何进行合成; - Step 2、 调用
getChangedCompositionTypes
方法,获取HWC返回的结果; - Step 3、 调用
applyCompositionStrategy
方法应用结果。
2.4.3.1、通知HWC校验Layer状态
通过Display::chooseCompositionStrategy()
方法开始执行通知HWC校验Layer的操作,这里会进一步执行HWComposer::getDeviceCompositionChanges()
方法,最终执行HWC HAL组件presentOrValidateDisplay()
方法,进入HWC中校验、合成Layer状态。
如果这里能够全部被HWC合成,那么这里将直接完成合成操作;否则,会等待GPU合成的FramBuffer给到HWC后再执行合成操作。
2.4.3.2、获取HWC返回结果
在执行HWComposer::getDeviceCompositionChanges()
方法时,传递了一个DeviceRequestedChanges
对象,这个对象用于接收HWC的校验结果,当执行完成校验后,会从HWC中读取相关校验值,并封装在DeviceRequestedChanges
中:
rust
// frameworks/native/services/surfaceflinger/DisplayHardware/HWComposer.h
struct DeviceRequestedChanges {
// HWC校验后返回的layer和该Layer合成类型
using ChangedTypes =
std::unordered_map<HWC2::Layer*,
aidl::android::hardware::graphics::composer3::Composition>;
// HWC校验后返回的当前Output亮度相关参数
// brightness字段: 让HWC可为客户端合成指定亮度空间,并指示RenderEngine是否调暗
// 客户端合成中的SDR层
// dimmingStage字段: 让HWC可配置RenderEngine应何时调暗内容
using ClientTargetProperty =
aidl::android::hardware::graphics::composer3::ClientTargetPropertyWithBrightness;
// HWC校验后返回的当前Display相关请求标记
// FLIP_CLIENT_TARGET: 指示RenderEngine提供一个新的Target Buffer
// WRITE_CLIENT_TARGET_TO_OUTPUT: 虚拟屏合成相关,设置时指示GPU合成直接写入Virtual output buffer
using DisplayRequests = hal::DisplayRequest;
// HWC校验后返回的Layer标记
using LayerRequests = std::unordered_map<HWC2::Layer*, hal::LayerRequest>;
ChangedTypes changedTypes;
DisplayRequests displayRequests;
LayerRequests layerRequests;
ClientTargetProperty clientTargetProperty;
};
2.4.3.3、应用HWC返回结果
接下来,在Output中执行applyCompositionStrategy()
方法对HWC校验返回的结果进行应用。
在应用时,也是将DeviceRequestedChanges上的属性更新到OutLayerCompositionState和OutputCompositionState上,这些属性会参与到后面的GPU合成流程。
2.4.4、执行GPU合成
如果HWC的返回结果中标记了Layer需要进行Client合成,会对这些Layer进行Client合成。
这一步从Output::finishFrame()
方法开始,并主要在Output::composeSurfaces()
中完成。
在应用HWC返回时,将是否进行Client合成结果更新给了outputState.usesClientComposition
属性,因此当该值在应用完HWC返回结果后为true时,便意味着需要进行Client合成。
在trace中,也可通过hasClientComposition
TAG看是否存在GPU合成:
Client合成的核心步骤如下:
- Step1、执行
RenderSurface::dequeueBuffer()
申请一块空闲Buffer作为"ClientTarget"; - Step2、根据HWC返回结果创建生成Client合成参数;
- Step3、执行
RenderEngine::drawLayers()
开始进行Client合成; - Step4、执行
HWComposer::setClientTarget()
方法将Client合成后的Buffer(ClientTarget)给到HWC中; - Step5、执行
HWComposer::presentAndGetReleaseFences()
方法通知HWC再次进行present,完成最终的合成。
其中Step5在接下来的postFrameBuffer操作操作完成。
从trace中可以看到以上步骤的时序:
2.4.5、执行postFrameBuffer
这步操作从Output::postFramebuffer()
开始,主要做两件事:
- 执行
HWComposer::presentAndGetReleaseFences()
向HWC再发送一次present命令,并从HWC获取releaseFence; - 执行
Layer::onLayerDisplayed()
方法,进行Buffer的release操作。
如果存在GPU合成,HWC中会present两次:
执行到这里,合成阶段就已完成。
2.5、合成后的处理
在完成合成操作后,会回到SurfaceFlinger::composite()
方法中,做一些收尾工作。
在这里,会将LayerSnapshot重新转移到Layer中:
cpp
// frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::moveSnapshotsFromCompositionArgs(
compositionengine::CompositionRefreshArgs& refreshArgs,
std::vector<std::pair<Layer*, LayerFE*>>& layers) {
......
// 将LayerSnapshot重新转移到Layer中
if (mLegacyFrontEndEnabled && !mLayerLifecycleManagerEnabled) {
for (auto [layer, layerFE] : layers) {
layer->updateLayerSnapshot(std::move(layerFE->mSnapshot));
}
}
}
并为layer设置releaseFence,并执行上一帧显示Buffer的释放等操作。