硬件混合渲染器 (HWC)

硬件混合渲染器(HWC)用于减少OpenGLES和GPU的合成工作,通过与SurfaceFlinger协作优化窗口合成。HWC支持叠加层、2D位块传送器等功能,并与窗口合成硬件通信。文章提到了HWC的实现步骤,包括逐步委托合成、优化以及针对不同场景的优化策略。HWC使用HIDL接口与SurfaceFlinger交互,并提供了图层和屏幕的管理以及VSYNC控制。在Android10及以上版本,HWC支持多个屏幕和虚拟屏幕的合成。
部署运行你感兴趣的模型镜像

硬件混合渲染器 (HWC) HAL 用于合成从 SurfaceFlinger 接收的图层,从而减少 OpenGL ES (GLES) 和 GPU 执行的合成量。

HWC 可以抽象出叠加层和 2D 位块传送器等对象来合成 Surface,并与专门的窗口合成硬件进行通信以合成窗口。使用 HWC 来合成窗口,而不是让 SurfaceFlinger 与 GPU 进行合成。大多数 GPU 都未针对合成进行过优化,当 GPU 合成来自 SurfaceFlinger 的图层时,应用就无法使用 GPU 进行自我渲染。

HWC 实现应该支持:

  • 至少 4 个叠加层:
    • 状态栏
    • 系统栏
    • 应用
    • 壁纸/背景
  • 大于屏幕的图层(例如壁纸)
  • 同时预乘的每像素 Alpha 混合和每平面 Alpha 混合
  • 受保护视频播放的硬件路径
  • RGBA 打包顺序、YUV 格式以及平铺、重排和步幅属性

要实现 HWC,请执行以下操作:

  1. 实现非运行的 HWC,并将所有合成工作发送到 GLES。
  2. 实现一种算法,以逐步将合成委托给 HWC。例如,仅将前 3 个或前 4 个 Surface 委托给 HWC 的叠加硬件。
  3. 优化 HWC。这可能包括以下操作:
    • 选择可以最大限度提高从 GPU 移除的负载的 Surface,并将其发送到 HWC。
    • 检测屏幕是否正在更新。如果不是,则将合成委托给 GLES 而不是 HWC,以节省电量。当屏幕再次更新时,继续将合成分载到 HWC。
    • 为常见用例做准备,例如:
      • 主屏幕,包括状态栏、系统栏、应用窗口和动态壁纸
      • 纵向和横向模式下的全屏游戏
      • 带有字幕和播放控件的全屏视频
      • 受保护的视频播放
      • 分屏多窗口

注意:用例应针对常规可预测的用途而不是边缘用例,以便最大限度地提高优化益处。

HWC 基元

HWC 提供了两个基元(图层屏幕)来表示合成工作及其与屏幕硬件的交互。此外,HWC 还提供对 VSYNC 的控制,以及对 SurfaceFlinger 的回调,用于通知它何时发生 VSYNC 事件。

HIDL 接口

Android 8.0 及更高版本使用一个名为混合渲染器 HAL 的 HIDL 接口,用于在 HWC 和 SurfaceFlinger 之间绑定 IPC。混合渲染器 HAL 取代了旧版 hwcomposer2.h 接口。如果供应商提供 HWC 的混合渲染器 HAL 实现,则混合渲染器 HAL 将直接接受来自 SurfaceFlinger 的 HIDL 调用。如果供应商提供 HWC 的旧版实现,混合渲染器 HAL 将从 hwcomposer2.h 加载函数指针,从而将 HIDL 调用转发到函数指针调用中。

HWC 提供相应函数来确定给定屏幕的属性;在不同的屏幕配置(例如 4k 或 1080p 分辨率)和颜色模式(例如原生颜色或真正的 sRGB)之间切换;以及打开、关闭屏幕或将其切换到低功率模式(如果支持)。

函数指针

如果供应商直接实现混合渲染器 HAL,则 SurfaceFlinger 会通过 HIDL IPC 调用其函数。例如,要创建图层,SurfaceFlinger 会在混合渲染器 HAL 上调用 createLayer()

如果供应商实现 hwcomposer2.h 接口,则混合渲染器 HAL 会调用 hwcomposer2.h 函数指针。在 hwcomposer2.h 注释中,HWC 接口函数由 lowerCamelCase 名称引用,这些名称并未作为命名的字段存在于接口中。几乎每个函数都是通过使用 hwc2_device_t 提供的 getFunction 请求函数指针来进行加载。例如,函数 createLayer 是一个 HWC2_PFN_CREATE_LAYER 类型的函数指针,当枚举值 HWC2_FUNCTION_CREATE_LAYER 传递到 getFunction 中时便会返回该指针。

有关混合渲染器 HAL 函数和 HWC 直通式函数的详细文档,请参阅 composer。有关 HWC 函数指针的详细文档,请参阅 hwcomposer2.h

图层和屏幕句柄

图层和屏幕由 HWC 生成的句柄操纵。这些句柄对 SurfaceFlinger 而言是不透明的。

当 SurfaceFlinger 要创建新图层时,它会调用 createLayer,该函数会针对直接实现返回 Layer 类型,或者针对直通式实现返回 hwc2_layer_t 类型。当 SurfaceFlinger 要修改该图层的属性时,它会将该 hwc2_layer_t 值以及进行修改所需的任何其他信息传递给相应的修改函数。hwc2_layer_t 类型的大小足以容纳一个指针或一个索引。

物理屏幕是通过热插拔创建的。在热插拔物理屏幕时,HWC 会创建一个句柄并通过热插拔回调将该句柄传递给 SurfaceFlinger。虚拟屏幕是由通过调用 createVirtualDisplay() 来请求屏幕的 SurfaceFlinger 创建的。如果 HWC 支持虚拟屏幕合成,则会返回一个句柄。然后,SurfaceFlinger 将屏幕的合成工作委托给 HWC。如果 HWC 不支持虚拟屏幕合成,则 SurfaceFlinger 会创建句柄并合成屏幕。

屏幕合成操作

如果 SurfaceFlinger 具有可合成的新内容,则会唤醒,且每个 VSYNC 唤醒一次。该新内容可以是来自应用的新图像缓冲区,也可以是一个或多个图层的属性更改。当 SurfaceFlinger 唤醒时,它将执行以下步骤:

  1. 处理事务(如果存在)。
  2. 如果存在新的图形缓冲区,则将其锁定。
  3. 如果步骤 1 或 2 导致显示内容更改,则执行新的合成。

为了执行新的合成,SurfaceFlinger 会创建和销毁图层或修改图层状态(如适用)。它还会使用 setLayerBuffer 或 setLayerColor 等调用,用图层的当前内容来更新图层。更新所有图层之后,SurfaceFlinger 会调用 validateDisplay,以告诉 HWC 检查各个图层的状态,并确定如何进行合成。尽管在某些情况下,SurfaceFlinger 会通过 GPU 回退来合成图层,但在默认情况下,SurfaceFlinger 会尝试配置每个图层,以使相应图层由 HWC 进行合成。

在调用 validateDisplay 之后,SurfaceFlinger 会调用 getChangedCompositionTypes,以查看 HWC 是否需要在执行合成之前更改任何图层的合成类型。要接受这些更改,SurfaceFlinger 需要调用 acceptDisplayChanges

如果已将任何图层标记为进行 SurfaceFlinger 合成,SurfaceFlinger 会将这些图层合成到目标缓冲区中。然后,SurfaceFlinger 通过调用 setClientTarget 将该缓冲区提供给屏幕,以便缓冲区可以在屏幕上显示,或者进一步与未标记为进行 SurfaceFlinger 合成的图层合成。如果没有将任何图层标记为进行 SurfaceFlinger 合成,则 SurfaceFlinger 会跳过合成步骤。

最后,SurfaceFlinger 会调用 presentDisplay,以告知 HWC 完成合成过程并显示最终结果。

多个屏幕

Android 10 支持多个物理屏幕。在设计要在 Android 7.0 及更高版本上使用的 HWC 实现时,还存在一些 HWC 定义中并不存在的限制:

  • 假设只有一个内部屏幕。内部屏幕是初始热插拔在启动期间报告的屏幕。内部屏幕在热插拔后无法断开连接。
  • 在设备的正常操作期间,除了内部屏幕之外,还可以热插拔任意数量的外部屏幕。该框架假设,在热插拔第一个内部屏幕之后,所有热插拔操作都是在外部屏幕上进行,因此如果添加了更多内部屏幕,它们将被错误地归类为 Display.TYPE_HDMI,而不是 Display.TYPE_BUILT_IN

尽管上述 SurfaceFlinger 操作按屏幕执行,但会对所有活动的屏幕依序执行这些操作,即使只更新了一个屏幕的内容也不例外。

例如,如果更新了外部屏幕,则顺序为:

// In Android 9 and lower:

// Update state for internal display
// Update state for external display
validateDisplay(<internal display>)
validateDisplay(<external display>)
presentDisplay(<internal display>)
presentDisplay(<external display>)

// In Android 10 and higher:

// Update state for internal display
// Update state for external display
validateInternal(<internal display>)
presentInternal(<internal display>)
validateExternal(<external display>)
presentExternal(<external display>)

虚拟屏幕合成

虚拟屏幕合成与外部屏幕合成类似。虚拟屏幕合成与物理屏幕合成之间的区别在于,虚拟屏幕将输出发送到 Gralloc 缓冲区,而不是发送到屏幕。硬件混合渲染器 (HWC) 将输出内容写入缓冲区,提供完成栅栏信号,并将缓冲区发送给使用方(例如视频编码器、GPU、CPU 等)。如果显示通道写入内存,虚拟屏幕便可使用 2D/位块传送器或叠加层。

模式

在 SurfaceFlinger 调用 validateDisplay() HWC 方法之后,每个帧处于以下三种模式之一:

  • GLES - GPU 合成所有图层,直接写入输出缓冲区。HWC 不参与合成。
  • MIXED - GPU 将一些图层合成到帧缓冲区,由 HWC 合成帧缓冲区和剩余的图层,直接写入输出缓冲区。
  • HWC - HWC 合成所有图层并直接写入输出缓冲区。

输出格式

虚拟屏幕的缓冲区输出格式取决于其模式:

  • GLES 模式 - EGL 驱动程序在 dequeueBuffer() 中设置输出缓冲区格式,通常为 RGBA_8888。使用方必须能够接受该驱动程序设置的输出格式,否则便无法读取缓冲区。
  • MIXED 和 HWC 模式 - 如果使用方需要 CPU 访问权限,则由使用方设置格式。否则,格式将为 IMPLEMENTATION_DEFINED,Gralloc 会根据使用标记设置最佳格式。例如,如果使用方是视频编码器,则 Gralloc 会设置 YCbCr 格式,而 HWC 可以高效地写入该格式。

注意:Android 10 取消了有关 eglSwapBuffers() 在渲染开始后将缓冲区移出队列的要求。缓冲区可能会立即退出队列。

同步栅栏

同步栅栏是 Android 图形系统的关键部分。栅栏允许 CPU 工作与并行的 GPU 工作相互独立进行,仅在存在真正的依赖关系时才会阻塞。

例如,当应用提交在 GPU 上生成的缓冲区时,它还将提交一个同步栅栏对象。当 GPU 完成写入缓冲区的操作时,该栅栏会变为有信号状态。

HWC 要求 GPU 在显示缓冲区之前完成写入缓冲区的操作。同步栅栏通过包含缓冲区的图形管道传递,并在缓冲区写入完成时发出信号。在显示缓冲区之前,HWC 会检查同步栅栏是否已发出信号,如果有,则显示缓冲区。

如需详细了解同步栅栏,请参阅硬件混合渲染器集成

您可能感兴趣的与本文相关的镜像

ACE-Step

ACE-Step

音乐合成
ACE-Step

ACE-Step是由中国团队阶跃星辰(StepFun)与ACE Studio联手打造的开源音乐生成模型。 它拥有3.5B参数量,支持快速高质量生成、强可控性和易于拓展的特点。 最厉害的是,它可以生成多种语言的歌曲,包括但不限于中文、英文、日文等19种语言

<think>嗯,用户想了解Android中GPU和HWC在hasClientComposition场景下的实现和使用情况。这个问题涉及到Android图形系统的核心机制,需要深入分析。用户可能正在开发图形相关的应用或系统模块,遇到了性能优化问题。从问题表述的专业性来看,用户应该有一定Android底层开发经验。我注意到用户引用了多个专业文档片段,包括SurfaceFlinger、minigbm、HWC等,说明ta对Android图形栈有基本了解。让我梳理下关键概念:hasClientComposition是HWC判断是否需要GPU合成的标志,当存在无法由硬件合成器直接处理的图层时(比如应用了复杂变换的OpenGLES图层),系统就会启用GPU合成。这种情况下GPU和HWC需要协同工作。从技术实现看,需要分三层说明:应用层通过Surface提交图形缓冲区,SurfaceFlinger作为合成器决策使用GPU还是HWC,底层通过minigbm这样的gralloc实现进行内存管理。特别要注意的是,当hasClientComposition为true时,GPU会先合成部分图层生成中间缓冲区,再由HWC进行最终合成输出。用户可能关心的痛点包括:如何减少GPU合成带来的性能损耗,HWC与GPU的协作机制是否会造成延迟,以及开发者如何优化自己的应用来避免触发ClientComposition。这些都需要在回答中重点解释。考虑到用户引用过minigbm相关内容,应该补充说明gralloc分配器在其中的作用——不同的缓冲区格式分配策略会影响HWC能否直接处理图层。比如NV12格式通常能被硬件加速,而RGBA格式可能迫使系统启用GPU合成。最后要提醒开发者注意事项:过度依赖ClientComposition会导致GPU负载升高,影响应用自身的渲染性能。可以通过Androiddumpsyssurfaceflinger命令实际验证合成策略。</think>## Android中hasClientComposition场景下GPU与HWC的实现与使用 `hasClientComposition` 是Android硬件合成器(HWC)中的一个关键标志,它表示当前帧**至少包含一个必须由GPU(通常指OpenGL ES)渲染的图层**。这种场景对图形性能和功耗有重要影响。 ### 1. 触发条件与判断逻辑 当满足以下任一条件时,HWC会设置 `hasClientComposition = true`: * **复杂图层处理**:图层应用了HWC硬件无法直接支持的变换(如旋转、缩放、复杂混合模式)。 * **特殊图层类型**:包含Protected DRM视频图层、需要颜色转换的HDR图层等。 * **HWC能力不足**:当前HWC硬件报告无法直接处理某个图层(`HWC2::Composition::Client`)。 * **强制GPU合成**:开发者通过`debug.sf.disable_client_composition_cache`等调试选项强制启用。 ```mermaid graph TD A[SurfaceFlinger收集图层] --> B[HWC::validate] B --> C{HWC能否处理所有图层?} C -- 是 --> D[hasClientComposition=false<br>全硬件合成] C -- 否 --> E[hasClientComposition=true<br>启用GPU合成] ``` ### 2. GPU与HWC协作流程 当 `hasClientComposition = true` 时,合成流程变为混合模式: 1. **GPU渲染中间结果**: * SurfaceFlinger调用OpenGL ES(通过RenderEngine),将无法由HWC直接处理的图层**合成到一个中间缓冲区**中。 * 该缓冲区通常分配自`minigbm`等gralloc实现[^2][^3],格式需兼容HWC(如RGBA8888)。 2. **HWC执行最终合成**: * 中间缓冲区作为一个"虚拟图层"(类型标记为`DEVICE`或`SOLID_COLOR`)与其它可由HWC处理的图层(如`DEVICE`、`CURSOR`)一起提交给HWC。 * HWC负责将所有图层(包括GPU合成的中间结果)最终合成到显示帧缓冲区(FrameBuffer)。 ### 3. 性能影响与优化考量 * **GPU开销增加**:额外的合成操作占用GPU资源,可能影响应用自身渲染性能(尤其游戏/高帧率应用)[^1]。 * **内存带宽消耗**:GPU合成需读写中间缓冲区,增加内存带宽压力。 * **潜在卡顿风险**:GPU合成耗时可能导致帧延迟(Jank)。 * **优化策略**: * **减少Client图层数量**:应用应尽量使用标准图层属性(避免非常规变换)。 * **HWC能力扩展**:驱动厂商应最大化HWC支持的合成能力(如缩放、旋转)。 * **中间缓冲区复用**:SurfaceFlinger复用中间缓冲减少分配开销。 * **格式选择**:确保中间缓冲区使用HWC友好的格式(如RGBA而非NV21[^4])。 ### 4. 开发者注意事项 * **调试工具**:使用`adb shell dumpsys SurfaceFlinger`查看每帧的合成策略(`HWC` vs `GLES`)及`hasClientComposition`状态。 * **性能分析**:关注`GPU utilization`和`Composition strategy`变化,识别过度依赖Client合成的场景。 * **格式兼容性**:若应用输出特殊格式(如相机NV21[^4]),需确认HWC是否支持直接显示或需GPU转换。 ### 5. minigbm与drm_hwcomposer的作用 * **minigbm**:提供跨平台gralloc实现,管理GPU合成所需中间缓冲区的分配与格式转换[^2][^3]。 * **drm_hwcomposer**:基于Linux DRM/KMS的HWC实现,高效处理混合合成场景(包括GPU中间结果),尤其在原生AOSP设备上[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值