当前位置: 首页 > 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.dtcms.com/a/319165.html

相关文章:

  • B 站 SEO 优化全景指南:从基础到进阶的实操方法
  • 贪心+矩阵算法
  • Oracle 关闭 impdp任务
  • 云原生安全挑战与治理策略:从架构思维到落地实践
  • 基于大数据的美食视频播放数据可视化系统 Python+Django+Vue.js
  • 解读 gpt-oss-120b 和 gpt-oss-20b开源模型
  • 仓库管理系统-20-前端之记录管理的联表查询
  • Android中视图测量、布局、绘制过程
  • 嵌入式 - 数据结构:二叉树
  • GitHub 上 Star 数量前 20 的开源 AI 项目
  • X4000 私有 5G 实验室入门套件
  • 90-基于Flask的中国博物馆数据可视化分析系统
  • MySQL的变量、控制流程和游标:
  • 智能升级新纪元:基于Deepoc具身模型外拓开发板的除草机器人认知进化
  • git工程多个remote 拉取推送
  • 配置VScode内置Emmet自动补全代码
  • leetcode 415.字符串相加
  • 如何重塑企业服务体验?
  • 六边形架构模式深度解析
  • 深度学习(1):pytorch
  • SurgRIPE 挑战赛:手术机器人器械位姿估计基准测试|文献速递-医学影像算法文献分享
  • Next.js 样式:CSS 模块、Sass 等
  • 前端技术架构设计文档(Vue2+Antd+Sass)
  • 安全合规2--网络安全等级保护2.0介绍
  • A Logical Calculus of the Ideas Immanent in Nervous Activity(神经网络早期的M-P模型)
  • Spring Boot整合PyTorch Pruning工具链,模型瘦身手术
  • 记录一次Inspur服务器raid配置流程
  • 【数据库】如何从本地电脑连接服务器上的MySQL数据库?
  • 某梆企业壳frida检测绕过
  • 网页前端CSS实现表格3行平均分配高度,或者用div Flexbox布局