当前位置: 首页 > news >正文

Android渲染/合成底层原理详解

一、核心组件详解

1. 核心硬件
  • GPU:执行图形渲染,将绘图指令转为像素数据(OpenGL ES/Vulkan)。

  • DPU(显示处理单元):负责图层合成(重叠区域计算/缩放/格式转换)。

  • HWC(硬件合成器):HAL(HWC)对合成操作进行了抽象,屏蔽了具体实现.绝大多数情况下hwc的实现者是DPU,除了合成工作外,hwc模块还负责送显以及发送VSync信号。

2. GraphicBuffer
  • 作用:GraphicBuffer是整个图形系统的核心,所有的渲染操作都将在此对象上进行,包括同步给GPU和HWC每当应用有显示需求时,应用会向系统申请一块GraphicBuffer内存,这块内存将会共享给GPU用于执行渲染工作,接着会同步给HWC用于合成和显示。我们可以把每一个GraphicBuffer对象看做是一个个渲染完成的图层。

  • 生命周期状态

    • FREE:空闲状态,APP可申请使用。

    • DEQUEUED:APP正在渲染(GPU写入数据)。

    • QUEUED:渲染完成,等待SF消费。

    • ACQUIRED:SF正在合成(HWC/GPU读取)。

  • 生命周期具体描述:

    渲染阶段:应用有绘图需求了,由GPU分配一块内存给应用,应用调用GPU执行绘图,此时使用者是GPU
    合成阶段:GPU渲染完成后将图层传递给sf进程,sf进程决定由谁来合成,hwc或者GPU如果使用GPU合成,那么此时buffer的使用者依旧是GPU,如果使用hwc合成,那么此时buffer的使用者是hwc。

    显示阶段:所有的buffer在此阶段的使用者都是hwc,因为hwc控制着显示芯片从生命周期可以看出GraphicBuffer对象在流转的过程中,会被GPU、CPU、DPU三个不同的硬件访问,如果同一块内存能够被多个硬件设备访问,就需要一个同步机制。在Android图形系统中,Fence机制就是用来保证跨硬件访问时的数据安全

  • 同步机制Fence(硬件锁)

    • 原理:每个硬件访问GraphicBuffer前需等待Fence信号(如GPU渲染完成才允许DPU读取)。

    • 类型:acquire_fence(消费者锁), release_fence(生产者锁)。

3. BufferQueue
  • 角色:协调生产者(APP)和消费者(SF)的核心队列。

  • 从名称就可以看出来,它是一个封装了GraphicBuffer的队列,BufferQueue对外提供了GraphicBuffer对象出列/入列的接口

  • 工作流程

    图表

  • 三重缓冲:默认3个GraphicBuffer循环使用,避免帧等待(VSync周期内可预渲染下一帧)。

4. Surface
  • 定位:APP的绘图入口,封装BufferQueue的生产者接口。

  • 详细描述:应用中所有的绘图操作最终都是在Surface中执行的,Surface作为图像的生产者,持有BufferQueue的引用,并且封装了出列和入列两个方法
    以2D绘图的流程来举例:

    1、需要显示图形时,首先创建一个Surface对象
    2、调用Surface#lockCanvas()获取Canvas对象
    3、调用Canvas的draw开头的函数执行一系列的绘图操作
    4、调用Surface#unlockCanvasAndPost()将绘制完成的图层提交,等待下一步合成显示

    第二步的[lockCanvas()]方法返回了Canvas对象供开发者绘图使用,其内部就调用了BufferQueue#dequeueBuffer()申请一块图形buffer,后续所有的绘图结果都会写入这块内存中
    第四步的[unlockCanvasAndPost()]方法内部调用了BufferQueue#queueBuffer()方法将绘制完成的Buffer入列,等待sf进程在下一次同步信号周期合成并完成送显
     

  • 关键方法

    • lockCanvas() → 调用dequeueBuffer()获取Canvas绘图。

    • unlockCanvasAndPost() → 调用queueBuffer()提交数据。

  • 底层绑定ANativeWindow(NDK层),为OpenGL ES/Vulkan提供绘图表面。

5. SurfaceFlinger (SF,由init.rc启动)
  • 职责

    • 接收所有Layer的GraphicBuffer。

    • 调用HWC合成图层。

    • 通过DRM/KMS驱动送显。

    • 职责总结:SurfaceFlinger进程负责接受来自APP进程的图形数据,调用hwc进行合成并完成最终的送显(“请求VSync”和“执行合成工作”)

  • 核心成员

    • mHWC:硬件合成器代理。

    • mEventThread:分发VSync-app/VSync-sf信号。

    • mPrimaryDispSync:预测硬件VSync模型。

6. HWComposer (HWC)
  • 作用:辅助SF完成接受硬件的VSync信号以及完成图层合成工作

  • 合成策略

    • 硬件合成:普通图层(无透明/变形),由DPU直接合成(低功耗)。

    • GPU合成:复杂特效图层(调用OpenGL ES)。

  • 查看方式adb shell dumpsys SurfaceFlinger → DEVICE(硬件合成)/ CLIENT(GPU合成)。

组件作用
GraphicBuffer图形内存块,存储渲染结果,共享给GPU/DPU
BufferQueue生产者-消费者模型管理GraphicBuffer,状态包括:FREE → DEQUEUED → QUEUED → ACQUIRED
SurfaceAPP绘图入口,封装BufferQueue的出列/入列操作
SurfaceFlinger (SF)系统服务进程:接收图层、调用HWC合成、送显

二、显示全流程

1. 进程启动与视图绑定

2. ViewRootImpl核心能力
  • 成员

    • mView:持有DecorView,控制视图树。

    • mSurface:绑定BufferQueue,管理绘图内存。

    • mChoreographer:接收VSync驱动绘制。

  • 首次绘制

    1. ViewRootImpl.setView() → requestLayout() → 请求VSync。

    2. VSync到达 → 执行performTraversals()(measure/layout/draw)。

3. 渲染加速机制
方式执行线程实现适用场景
软件渲染UI线程CPU直接绘制到Canvas简单视图/兼容模式
硬件加速RenderThread构建DisplayList → GPU渲染复杂动画/现代APP
SurfaceView任意线程独立Surface → 直接提交Buffer游戏/视频播放器
4. SF合成五部曲
  1. 预处理 (preComposition):检查新增图层。

  2. 重建图层栈 (rebuildLayerStacks):计算脏区域/Z序。

  3. 准备HWC (setUpHWComposer):分配合成方式。

  4. 执行合成 (doComposition):

    • GPU合成:HWC无法处理的图层。

    • 硬件合成:DPU直接合成图层。

  5. 送显 (postComposition):DRM提交帧 → 等下次硬件VSync显示。


三、VSync同步机制

1. VSync信号流

2. 关键优化
  • VSync Offset:错开APP/SF的VSync信号(APP先执行,SF延迟执行),实现流水线处理。

  • 同步屏障:VSync到来时阻塞普通消息,优先执行绘制(ViewRootImpl#scheduleTraversals())。


四、常见问题

Q1: 为什么要有Fence机制?

:防止多硬件(GPU/DPU)同时写GraphicBuffer导致数据竞争。例如:

  • GPU渲染未完成时,DPU若读取Buffer会显示残缺帧。

  • Fence工作流:DPU消费前等待acquire_fence(GPU渲染完成信号)。

Q2: SurfaceView为什么不会阻塞UI线程?

  • 拥有独立Surface和BufferQueue,渲染在子线程执行。

  • 不受主线程VSync约束,通过unlockCanvasAndPost()直接提交帧。(SurfaceView让应用无需等待VSync信号的到来便可以执行绘制工作,这是它和普通View最大的区别)

Q3: 丢帧的根本原因是什么?

任一阶段超时

  1. APP渲染 > 16.6ms(60Hz)

  2. SF合成 > 16.6ms

  3. Buffer排队(未及时释放FREE Buffer)

Q4: HWC如何提升性能?

  • 硬件合成比GPU合成功耗低30%+。

  • 减少GPU负载 → 降低发热/提升续航。

Q5: 三重缓冲如何减少卡顿?

:允许APP在SF消费前一帧时,提前渲染下一帧(VSync周期内可排队2帧),避免等SF释放Buffer。


总结:

Q:Android点击应用图标到画面显示的完整流程。

A
整个过程分为四个阶段:

  1. 进程启动与视图创建

    • AMS通知Zygote孵化APP进程,创建ActivityThread。

    • Activity创建PhoneWindow和DecorView,通过WindowManager关联到ViewRootImpl。

    • ViewRootImpl初始化Surface和Choreographer,准备接收VSync信号。

  2. VSync驱动绘制

    • APP首次调用requestLayout()请求VSync-app。

    • VSync-app到达 → Choreographer触发ViewRootImpl#performTraversals()

    • 执行measure/layout/draw:

      • 软件渲染:UI线程直接绘制Canvas。

      • 硬件加速:构建DisplayList → RenderThread异步执行GPU渲染。

    • 绘制结束 → Surface提交GraphicBuffer到BufferQueue。

  3. SurfaceFlinger合成

    • BufferQueue通知SF有帧就绪 → SF请求VSync-sf。

    • VSync-sf到达 → SF执行合成五部曲:

      1. 预处理检查新图层。

      2. 重建图层栈(计算脏区域/Z序)。

      3. HWC分配合成方式(硬件/GPU)。

      4. 执行合成并提交结果到显示框架。

    • HWC等待下次硬件VSync切换帧。

  4. 显示

    • 显示器在硬件VSync信号到来时切换帧缓冲区,用户看到画面。

参考资料:https://juejin.cn/post/7132777622487957517#heading-43

http://www.lryc.cn/news/612944.html

相关文章:

  • MySQL GROUP BY 语句详细说明
  • 《算法导论》第 9 章 - 中位数和顺序统计量
  • NAS技术在县级融媒体中心的架构设计与安全运维浅析
  • 医疗AI中GPU部署的“非对等全节点架构“方案分析(下)
  • MHA架构实战
  • 【R语言】 高清美观的 MaxEnt 刀切图(Jackknife)绘制——提升论文质量
  • Docker离线安装MinIO及数据迁移
  • 【R语言】重新绘制高清MaxEnt的单因素响应曲线图像
  • 把 apipost 的 md 文档转化成 json数据
  • 【论文阅读】基于元模型的体系知识图谱构建
  • 遍历节点设备属性
  • mac中多版本JDK配置和切换
  • 机器学习算法篇(四)决策树算法
  • Qwen-Image开源模型实战
  • 使用萤石云播放视频及主题模版配置
  • VFTO与局部放电-高压设备绝缘系统的双重挑战与防护策略
  • Keil MDK-ARM V5.42a 完整安装教程
  • rk3588s vscode索引失败的问题
  • 12-netty基础-手写rpc-编解码-04
  • web前端结合Microsoft Office Online 在线预览,vue实现(PPT、Word、Excel、PDF等)
  • 表单元素与美化技巧:打造用户友好的交互体验
  • 【LVGL自学笔记暂存】
  • LINUX-批量文件管理及vim文件编辑器
  • VBA之Word应用第四章第一节:段落集合Paragraphs对象(一)
  • 11-netty基础-手写rpc-支持多序列化协议-03
  • 从零开始构建情绪可视化日记平台 - React + TypeScript + Vite
  • 芯谷科技--高效噪声降低解决方案压缩扩展器D5015
  • 30-Hive SQL-DML-Load加载数据
  • 微算法科技(NASDAQ:MLGO)利用集成学习方法,实现更低成本、更稳健的区块链虚拟货币交易价格预测
  • 51单片机