尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Android: 显示过程
基础1.硬件基石渲染与合成分离Android图形显示依赖两大核心硬件单元GPU图形处理器负责渲染。将应用下发的绘图指令如画圆、画线转化为具体的像素数据二维数组产出单个图层。DPU显示处理器负责合成与送显。将多个渲染好的图层如状态栏、壁纸、应用界面按Z轴顺序合并计算重叠区域的最终颜色并驱动屏幕显示。HWC硬件合成器HAL层的抽象接口厂商实现DPU驱动。面试核心点HWC有图层合成数量上限超出部分会回退给GPU处理标记为CLIENT合成GPU处理不完则丢帧。2.核心数据流转GraphicBuffer与BufferQueueGraphicBuffer图形数据的载体本质是一块共享内存分配在RAM移动端无独立显存。Fence机制跨硬件同步锁。GPU/DPU/CPU访问GraphicBuffer前需检查Fence信号防止数据读写冲突如GPU还在写DPU就来读导致花屏。BufferQueue基于生产者-消费者模式。APP是生产者Surface作为图像的生产者持有BufferQueue的引用并且封装了出列和入列两个方法dequeue获取空缓冲queue提交绘满的缓冲SFSurfaceFlinger是消费者acquire取出渲染完的缓冲release释放回空闲队列。状态流转FREE → DEQUEUED → QUEUED → ACQUIRED → FREE。3.双端进程职责APP进程生产者通过ViewRootImpl持有Surface触发绘制后提交Buffer给BufferQueue。SurfaceFlinger进程消费者核心系统服务接收APP的Buffer执行图层合成最后通过DRM提交给硬件显示。4.VSync驱动机制灵魂为了画面流畅系统引入VSync垂直同步信号。为了解决“渲染合成”耗时长的问题Offset偏移量设计让APP和SF接收信号的时机错开理论上可在一个硬件周期内完成两步降低触控延迟。正常的显示流程VSync1 VSync2 VSync3 │ │ │ APP 开始绘制 │ └── queueBuffer │ SF 获取Buffer 调用hwc合成, 执行合成 │ └── 提交显示 │ Display 扫描显示ViewRootImpl.requestLayout() 的执行流程在 Activity 的 onResume 周期后会调用 WindowManager.addView() 方法 其内部 会 创建 ViewRootImpl 并且会 通过 Binder 给 WMS 添加 窗口。ViewRootImpl.requestLayout() ↓ scheduleTraversals() ↓ 1. 向 MessageQueue 插入同步消息屏障 postSyncBarrier() ↓ 2. 向 Choreographer 注册 CALLBACK_TRAVERSAL ↓ 3. Choreographer 请求/等待下一次 VSync ↓ VSync 到来 ↓ DisplayEventReceiver 收到 VSync ↓ 向主线程 MessageQueue 投递一个“异步消息” ↓ 因为队列前面有同步消息屏障 普通同步消息先被挡住 异步消息可以越过屏障 ↓ 主线程 Looper 取出这个异步消息 ↓ 执行 Choreographer.doFrame() ↓ 执行 CALLBACK_TRAVERSAL ↓ ViewRootImpl.doTraversal() ↓ 先移除同步消息屏障 removeSyncBarrier() ↓ performTraversals() ↓ measure → layout → draw (绘制三部曲)measure过程和layout过程都是发生在CPUdraw不同如果开启硬件加速那么draw的过程发生在GPU。requestLayout() 最终会调用ViewRootImpl.scheduleTraversals()首先向主线程的 MessageQueue插入一个同步消息屏障然后通过 Choreographer 注册 Traversal 回调等待 下一次 VSync 信号。当 VSync 到来后DisplayEventReceiver 接收到 VSync并通过 Choreographer 向主线程消息队列投递一个异步消息。由于同步消息屏障会阻塞普通同步消息而异步消息可以越过屏障所以这一帧的绘制任务能够被优先处理。随后主线程执行 Choreographer.doFrame()触发 Traversal 回调进入 ViewRootImpl.doTraversal()移除同步消息屏障再调用performTraversals()最终完成 View 的 measure、layout 和 draw 流程。后续 从绘制 到 屏幕 显示的过程我会把整个流程分为四个阶段生产者入队 → SF调度触发 → 合成决策与执行 → 硬件呈现。第一阶段生产者提交APP侧APP完成一帧绘制后调用Surface.queueBuffer()。此时GraphicBuffer 被放入 BufferQueue。这一步本质上是释放生产者锁让消费者SF有机会获取。第二阶段SF唤醒与VSync对齐核心调度3. BufferQueue通知SFonFrameAvailable()。4. SF调用signalLayerUpdate()→requestNextVSync()。注意SF不会立即合成而是等待下一个VSync信号。这么做是为了对齐刷新率避免在屏幕刷新中途写入数据导致撕裂。第三阶段VSync到来与消息驱动双消息机制5. VSync信号触发 DisplayEventReceiverSF开始处理。6. SF首先发INVALIDATE消息在handleMessageInvalidate()中处理事务Transaction和图层更新。这一步是为了判断是否有图层需要重绘或合成如果没有变化则跳过合成以省电。7. 若需要合成则发REFRESH消息进入真正的合成流程。这种将“检查”和“执行”分离的设计是为了高效处理高频UI变化。第四阶段合成与送显SF核心工作8. 在handleMessageRefresh()中SF执行五步标准合成流水线preComposition()最后检查是否有新Buffer防丢帧。rebuildLayerStacks()计算可见区域和脏区只合变化的部分。setUpHWComposer()决策分水岭。决定哪些层走HWC硬件合成器哪些层走GPUClient合成。原则是能走HWC就不走GPU因为HWC是硬解码专用电路功耗更低且零拷贝。doComposition()执行合成。GPU合成会渲染到FramebufferHWC合成则只是配置显示控制器的寄存器。postComposition()收尾触发BufferQueue的release回调让APP复用Buffer。最终Display Controller 显示控制器基于VSync周期扫描Framebuffer将图像发送给屏幕用户看到画面。APP 绘制完成后通过 Surface.queueBuffer() 将 GraphicBuffer 提交到 BufferQueue。BufferQueue 可以理解为 APP 和 SurfaceFlinger 之间传递图形 Buffer 的缓冲队列。SF 侧发现有新的 Buffer 可以消费后会安排下一次 VSyncVSync 到来时SF 先检查图层和事务是否发生变化如果需要合成就通过 GPU/HWC 完成多个 Layer 的合成并将最终显示内容提交给显示系统。显示控制器会按照 VSync 对应的显示时序切换到新的显示 Buffer并逐行扫描输出到屏幕最终用户看到这一帧。GraphicBuffer 这个图层某一帧的像素数据BufferQueue 这个图层的 Buffer 流转队列
RELATED

相关推荐

游戏角色高质量还原:从角色分析到4K拍摄制作全流程技术解析

游戏角色高质量还原:从角色分析到4K拍摄制作全流程技术解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/10/25 11:57:26
短视频平台选择逻辑:从算法匹配到用户体验的深度解析

短视频平台选择逻辑:从算法匹配到用户体验的深度解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/10/15 18:42:43
RobotStudio 6.08 安装指南:从许可证服务到功能验证的完整流程

RobotStudio 6.08 安装指南:从许可证服务到功能验证的完整流程

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/9/19 13:34:06
MORE NEWS

更多资讯

📰

.NET Core 配置与选项

在现代 .NET Core 开发中,配置与选项系统早已脱离了传统 App.config 的单一模式,形成了一套支持多源混合、强类型绑定、动态更新、可高度扩展的完整体系。1. 获取配置与选项所有配置的读取、合并、管理都围绕 IConfiguration 对象的 Providers 集合展开&…

📰

Python基础技术练习

第一题:新建 practice1.py,用 print() 输出你的姓名、年龄、学校,三行内容(分别用一个 print)分析说明: print() 是输出函数,默认输出结束自动换行。三个独立print语句,分别输出姓名…

📰

FunASR安装

在 Windows 上配置和运行 FunASR,最省事的路子是走 Docker 一键部署,或者用现成的整合包‌。下面按不同需求给出对应方案。🐳 方案一:Docker 一键部署(推荐,适合离线转写服务) 这是目前最省心的…

📰

8、【MOD开发】【骑砍2】跨平台MOD构建环境(八)/:游戏根 bin 与模块 bin——运行程序集的两种归属

【声明】本博客所有内容均为个人业余时间创作,所述技术案例均来自公开开源项目(如Github,Apache基金会),不涉及任何企业机密或未公开技术,如有侵权请联系删除 8、【MOD开发】【骑砍2】跨平台MOD构建环境&am…

📰

C++模板:泛型编程、函数模板与类模板详解

文章目录模版1. 泛型编程2. 函数模版2.1函数模版格式:2.2 函数模版原理2.3 函数模版的实例化2.4 模版参数的匹配原则3. 类模版3.1 类模版的定义格式3.2类模版的实例化模版 1. 泛型编程 在C语言中要写交换函数时要针对不同的参数类型来写多个对应的函数 void swap…

📰

40秒生成3分钟半的完整歌曲:Yue2-3B-GGUF长音频性能实测全报告(RTX 5090)

40秒生成3分钟半的完整歌曲:Yue2-3B-GGUF长音频性能实测全报告(RTX 5090) 📌 一句话总结:Yue2-3B-GGUF 是 Yue2-3B 文生音乐模型的 audio.cpp 原生 GGUF 权重包。实测在 RTX 5090 上,Q8_0 量化组合约 39 秒…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬