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

Android的UI View是如何最终绘制成一帧显示在手机屏幕上?

Android的UI View是如何最终绘制成一帧显示在手机屏幕上?

Android View的onmeasure,onlayout和ondraw过程中,会生成绘制指令,存在DisplayList缓存区,每个View内部都有一个DisplayList,当View需要重绘时,这个View被标记为dirty,在draw的时候,View的DisplayList都会被更新,这个时候的DisplayList就会保存最新的绘制指令,这都是在主线程完成。在绘制流程走完,生成一系列DisplayList 绘制指令后,随后这些绘制指令会被同步到Render Thread。DisplayList可以认为是一系列绘制指令(比如将canvas的命令转换为OpenGL指令)。
VSYNC全称 Vertical Synchronization,垂直同步,简单的理解为一种时钟中断。Android的VSYNC消费者有两个,对应两类VSYNC信号,分别是VSYNC-app和VSYNC-sf,所对应的也是上层View绘制和SurfaceFlinger合成。App代表的是生产者,sf代表的是消费者,两者交付的中间产物则是 surface buffer。

手机屏幕渲染显示的一个关键,是对图像数据的生产和消费。生产和消费的对象,是 BufferQueue里的Buffer。
生产者使用 dequeueBuffer 取出可用的 Buffer,往里面填充图像数据(CPU或GPU 生产),然后 queueBuffer 把图像数据放回到 BufferQueue ;消费者使用 requireBuffer 取出可用于屏幕显示的图像数据,然后显示,接着再把 Buffer release 后,返还 BufferQueue。

要理解Android UI渲染流程,就要了解谁是生产者(Producer),谁是消费者(Consumer),以及 BufferQueue 怎么轮转。

生产者和消费者双方:
生产者之一就是App应用。不论是Android UI组件本身的绘制,还是播放器解码出来的视频帧,还是从手机摄像头取出的拍摄数据,App 都是图像数据的生产者。
消费者是 SurfaceFlinger 和 HWC(Hardware Composer),对各生产者生产出来 Buffer 进行合成,显示到屏幕。

Choreographer 和 Vsync

Choreographer(编舞者) 和 Vsync 协调生产者何时生产,消费者何时消费。Choreographer 本质是一个 Java 类。简单说,Choreographer 作用是协调输入、动画、和绘制等任务的执行时机,它从显示子系统接收定时脉冲VSYNC,然后安排渲染下一个显示 Frame 的部分工作。
如果生产者和消费者的行为都是非常激进:生产者先生产,然后把 Buffer 放回到 BufferQueue 后,消费者马上消费,然后生产者又马上拿出来生产,假设两者不会有时间间隙,全过程持续进行。
这有什么问题吗?
手机屏幕刷新率在 60Hz ~ 144Hz 之间。1S内,每次刷新间隔即约7ms~16ms,要产生流畅的画面,1S按照60帧~144帧就可以,但如果以这样的方式生产和消费,那么大概率会产出很多无用功,带来功耗问题。因此需要一个协调者来协调,平衡功耗和绘制节奏。
这就是Choreographer(编舞者):a person who composes the sequence of steps and moves for a performance of dance.
Choreographer 协调生产者什么时候生产,什么时候绘制一帧。既然要协调,那么需要一个协调依据,这个依据就是 Vsync 信号。
Vsync 信号一般是由硬件产生,每个 Vsync 信号之间的时间,就是每一帧生产 / 消费的间隙。Vsync 有两种,Vsync-app 和 Vsync-sf,前者用于告诉 Choreographer,是时候协调 app 生产了;后者用于告诉 SurfaceFlinger,是时候来消费合成并显示到屏幕了。
Vsync-app 和 Vsync-sf 几乎同时发生的(不同手机厂商自定义 Vsync Offset ,每个手机可能不尽完全一样),Android系统使用数字信号的变化来表示 Vsync 的发生,从 1 到 0 或者从 0 到 1 都表示发生了 Vsync 信号。


Vsync-app 和 Vsync-sf 发生时,Choreographer 是怎么协调的?


Choreographer 的引入,主要是配合 Vsync ,给App 的渲染提供一个稳定的 Message 处理时机,系统通过对 Vsync 信号周期的调整,控制每一帧绘制的时机。比如手机的屏幕刷新率是 60Hz,也就是 16.6ms 刷新一次,系统为了配合屏幕的刷新频率,将 Vsync 的周期也设置为 16.6 ms,每隔 16.6 ms ,Vsync 信号到来唤醒 Choreographer 来做 App 的绘制操作 ,如果每个 Vsync 周期应用都能渲染完成,那么应用的 fps 就是 60 ,给用户的感觉就是流畅。

为什么App 需要重绘?既然重绘,那么是 App 内容发生变化,这里的内容变化由多种情况发生:用户通过物理按键或者手指触摸屏幕,产生了交互行为,App 需要响应交互,做出相应的UI变化,比如改变按钮的文字、颜色等;
动画过程,每隔一段时间触发一次内容的改变,比如改变背景透明度,View 位置等;
视频播放场景。
典型的,以用户交互行为导致重绘的场景为例,收到 Vsync-app 信号后,Choreographer:
分派触控事件;
Measure、Layout 和 Draw等;
以上都是发生在主线程,其中 Draw:
如果开启了硬件(GPU)加速(默认都是开了的),那么不会走 CPU 绘制,这里会产生用来描述绘制行为的 DisplayList;
没开启硬件加速的话,会调用 libSkia 来绘制(CPU);
不要混淆硬件加速和 Software Layer / Hardware Layer 。开启硬件加速后,可以用 Hardware Layer 来对内容本身很少改变的 View 来做显存上的缓存;而不开启硬件加速,或者不支持 Hardware Layer 的话,可以选择使用 Software Layer 来告诉 UI Framework 帮你构造 Bitmap 缓存。对于不使用 Layer 的情况,View 该怎么绘制就怎么绘制。
在开启硬件(GPU)加速后,主线程就会把 DisplayList 同步给 RenderThread,RenderThread 这里可以做一些优化的操作(比如 Reordering),然后提交给 GPU 进行绘制(这里会进行 dequeueBuffer),当绘制完毕后(eglSwapBuffers),通过 queueBuffer 把 Buffer 放回到 BufferQueue 里。

 Vsync-sf 发生后,SurfaceFlinger 就跟 HAL 打交道,把图像数据渲染到 Display 上。


SurfaceFlinger跟 Hardware Composer 打交道,把各个 Layer 的数据进行合成,然后交由 HardwareComposer 显示。

SurfaceFlinger及Android应用RenderThread角度观察Jank丢帧卡顿_图像卡顿 surfaceflinger-CSDN博客文章浏览阅读904次,点赞14次,收藏28次。在Android系统中,Jank(卡顿)问题主要涉及CPU、GPU和Display三个部分。CPU负责计算帧数据,GPU进行图形渲染,渲染后的数据存储在Buffer中,最后由Display呈现到屏幕。Google在Android 4.1中引入了Project Butter,通过Vsync信号优化了帧处理流程,确保CPU和GPU在收到Vsync信号后立即处理下一帧数据。应用在绘制前需从SurfaceFlinger管理的BufferQueue申请Buffer,渲染完成后通过queueBuffer将数据返回给Bu_图像卡顿 surfaceflinger https://blog.csdn.net/zhangphil/article/details/148176456Android屏幕刷新率与FPS(Frames Per Second) 120hz_帧时间16.67ms多少帧-CSDN博客文章浏览阅读1.5k次,点赞14次,收藏17次。Android屏幕刷新率与FPS的关系决定了显示流畅度。120Hz屏幕每秒刷新120次(8.33ms/次),而FPS指系统生成帧数。理想状态下FPS应与刷新率匹配,如120FPS对应120Hz。当FPS低于刷新率时会出现卡顿,高于则浪费资源。Android 12引入Surface.setFrameRate()API让应用指定帧率。系统通过BufferQueue管理帧缓冲,渲染完成数据通过queueBuffer传给SurfaceFlinger显示。VSync信号同步处理流程,确保CPU/GPU及时处理帧数据,_帧时间16.67ms多少帧 https://blog.csdn.net/zhangphil/article/details/148543654

Android trace presentFence屏幕显示的帧_android surfaceflinger presentfence-CSDN博客文章浏览阅读1k次,点赞25次,收藏25次。在Android系统中,presentFence是屏幕显示帧的关键信号,当帧成功显示时,presentFence会发出信号。FrameMissed、GpuFrameMissed和HwcFrameMissed表示上一次合成的结果,SurfaceFlinger在每次被Vsync-sf唤醒时会检查上一次合成的presentFence是否已发出信号,若未发出则认为是帧丢失。BufferTx在queueBuffer后增加,在SurfaceFlinger合成时减少,其内有可用Buffer时,SurfaceFlinger_android surfaceflinger presentfence https://blog.csdn.net/zhangphil/article/details/148099387

http://www.dtcms.com/a/314204.html

相关文章:

  • Android Espresso 测试框架深度解析:从入门到精通
  • imx6ull-驱动开发篇8——设备树常用 OF 操作函数
  • 力扣热题100——哈希表
  • 大模型×垂直领域:预算、时间、空间三重夹击下的生存法则
  • 基于ensp的防火墙安全策略及认证策略综合实验
  • Flink CDC 介绍
  • PHP-分支语句、while循环、for循环
  • 深入理解Spring中的循环依赖及解决方案
  • 鸿蒙南向开发 编写一个简单子系统
  • 机器学习——学习路线
  • MySQL进阶:(第八篇)深入解析InnoDB存储架构
  • 高效洗牌:Fisher-Yates算法详解
  • 软考 系统架构设计师系列知识点之杂项集萃(118)
  • 直播 app 系统架构分析
  • 如何在 Ubuntu 24.04 LTS 上安装 Docker
  • 计算机网络:
  • 团购商城 app 系统架构分析
  • (五)系统可靠性设计
  • android TextView lineHeight 是什么 ?
  • 国产化低代码平台如何筑牢企业数字化安全底座
  • 学习日志27 python
  • 远程机器操作--学习系列004
  • Vue Router快速入门
  • 数据从mysql迁移到postgresql
  • Petalinux快捷下载
  • 项目一:Python实现PDF增删改查编辑保存功能的全栈解决方案
  • WPF 按钮背景色渐变
  • LLM开发——基于Graph RAG知识图谱检索增强生成
  • steam Rust游戏 启动错误,删除sys驱动,亲测有效。
  • MySQL 约束知识体系:八大约束类型详细讲解