可以理解为上层生产,下层消费模型。

其中每一层之间的数据传递是使用Buffer(图形缓冲区)作为载体:

① 屏幕刷新速率比系统帧速率快
屏幕将无法读取下一帧,所以只能继续显示当前一帧的图形,造成一帧显示多次,也就是卡顿。
② 系统帧速率比屏幕刷新率快
将会导致屏幕上半部分是上一帧的图形,而下半部分是下一帧的图形,造成屏幕上显示多帧,也就是屏幕撕裂。
上面两种情况,都会导致问题,根本原因就是两个缓冲区的操作速率不一致,解决办法就是让屏幕控制前后缓冲区的切换,让系统帧速率配合屏幕刷新率的节奏.

垂直同步(VSync):当屏幕从缓冲区扫描完一帧到屏幕上之后,开始扫描下一帧之前,发出的一个同步信号,该信号用来切换前缓冲区和后缓冲区。

1.2 SurfaceFlinger-图形合成者

如果说屏幕是消费者,那么SurfaceFlinger相对屏幕来说就是生产者,其具有如下特性:

  • 作为上层应用的消费者,硬件层的生产者。
  • 负责图形的合成
  • 和ActivityManagerService一样,是一个系统服务.和ams不同的是sf是进程,ams是ss进程的一个线程

通过下面的这个界面分析SF:

界面很简单,拆开来看,包含微信、悬浮工具箱、通知栏、底部虚拟按键栏:

我们可以先这样理解上面这幅图,上层每一个界面,其实都对应SufaceFlinger里的一个Surface对象,上层将自己的内容绘制在对应的Surface内.
接着,SufaceFlinger需要将所有上层对应的Surface内的图形进行合成,具体看下图:

没错,SurfaceFlinger就是将多个Surface里的内容进行合成,最后提交到屏幕的后缓冲区,等待屏幕的下一个垂直同步信号的到来,再显示到屏幕上。

我们会发现SufaceFlinger通过屏幕后缓冲区与屏幕建立联系。同时通过Surface与上层建立联系。从而起到一个承上启下的作用,是Android图形系统结构中的关键组成部分。

为了继续往上层讲,我们需要了解什么是Surface:

  • 对应上层的一个Window(对话框、Activity、状态栏)
  • 作为上层图形绘制的画板
  • Canvas是画笔,上层通过调用Canvas的API向Surface上绘制图形
  • Surface内部存在多个缓冲区,形成一个BufferQueue

notes: 直播仅仅一个layer同时没有遮挡。普通GUI使用,分成工具栏,状态栏,内容栏。每次ui 刷新则 3个layer SF将重新合成发给opengl.

如果说SurfaceFinger是图形的合成者,那么图形的提供者就是上层。文章一开始就提到,图形的传递是通过Buffer作为载体,Surface是对Buffer的进一步封装,也就是说Surface内部具有多个Buffer供上层使用,如何管理这些Buffer呢?请看下面这个模型:

Surface内部提供一个BufferQueue,与上层和SurfaceFlinger形成一个生产者消费者模型,上层对应Producer,SurfaceFlinger对应Consumer。三者通过Buffer产生联系,每个Buffer都有四种状态:

Free:可被上层使用;Dequeued:出列,正在被上层使用;Queued:入列,已完成上层绘制,等待SurfaceFlinger合成;Acquired:被获取,SurfaceFlinger正持有该Buffer进行合成

Buffer的一次转移过程大致为:

  1. 从BufferQueue转移到上层
  2. 上层绘制完成再放回BufferQueue
  3. 接着SurfaceFlinger再拿去合成
  4. 最后又放回BufferQueue

如此循环,形成一个Buffer被循环使用的过程。
notes: surface的bufferqueue是有顺序的,每次SF取走每个surface的bufferqueue header合成.
接下来看看上层是如何将图形绘制到Surface的Buffer中。

1.3 上层绘图

上层绘图的大体流程见下图:

Surface里的Buffer作为上层的画板,Canvas作为画笔,通过调用Canvas的API完成图形的绘制,上层通过调用draw方法来调用Canvas的API。
other: 这里的draw方法并没有真正的将图形绘制到缓冲区,而是记录了一下绘制命令,具体需要了解DisplayList相关知识,后面会对其进行分析。

从流程上看:

  1. 测量View的宽高(Measure)
  2. 设置View的宽高位置(Layout)
  3. 创建显示列表,并执行绘制(Draw)
  4. 生成多边形和纹理
  5. 对多边形和纹理进行栅格化操作

从执行者的角度看:

  1. CPU:Measure,Layout,纹理和多边形生成,发送纹理和多边形到GPU
  2. GPU:将CPU生成的纹理和多边形进行栅格化以及合成

上面说的的纹理和多边形还有栅格化以及合成,这里不做具体的讲解,需要了解的是图形的绘制流程需要经过这些操作.从上面的分析可以看出,上层绘制图形时需要经过CPU计算,再经过GPU计算。

经过上面的分析,整个Android的图形绘制大体流程已经分析完成,接下来将会分析一些流程的具体实现,分析的内容包括:

  • Android 4.1 加入的VSync信号同步到上层以及三缓冲
  • 从上层往下层具体分析每一步流程

2. VSync以及三缓冲

notes: 没有vsync cpu和GPu不同步,造成卡顿或者拼接错误.
这部分只需要知道vsync作用和基本使用即可.

2.1 Drawing Without VSync
2.2 Drawing With VSync

2.2.1 Choreographer VSync信号的上层接收者

可以发现,Choreographer需向SurfaceFlinger注册一个VSync信号的接收器DisplayEventReceiver.
同时在Choreographer的内部维护了一个CallbackQueue,用来保存上层关心VSync信号的组件,包括ViewRootImpl,TextView,ValueAnimator等。

再看看上层接收VSync的时序图:

知道了Choreographer是上层用来接收VSync的角色之后,我们需要进一步了解VSync信号是如何控制上层的绘制的:

一般,上层需要绘制新的UI都是因为View的requestLayout或者是invalidate方法被调用触发的,我们以这个为起点,跟踪上层View的绘制流程:

  1. requestLayout或者invalidate触发更新视图请求
  2. 更新请求传递到ViewRootImpl中,ViewRootImpl向主线程MessageQueue中加入一个阻塞器,该阻塞器将会拦截所有同步消息,也就是说此时,我们再通过Handler向主线程MessageQueue发送的所有Message都将无法被执行。
  3. ViewRootImpl向Choreographer注册下一个VSync信号
  4. Choreographer通过DisplayEventReceiver向framework层注册下一个VSync信号
  5. 当底层产生下一个VSync消息时,该信号将会发送给DisplayEventReceiver,最后传递给Choreographer
  6. Choreographer收到VSync信号之后,向主线程MessageQueue发送了一个异步消息,我们在第二步提到,ViewRootImpl向MessageQueue发送了一个同步消息阻塞器。
    这里Choreographer发送的异步消息,是不会被阻塞器拦截的。
  7. 最后,异步消息的执行者是ViewRootImpl,也就是真正开始绘制下一帧了

Vsync信号的产生过程。
1:HWC硬件产生Vsync信号,给DispSync添加样本
2:DispSync根据样本计算Vsync周期,然后产生软件Vsync信号。计算Vsync事件会根据不同的Listenr计算不同的时间.
3:DisplaySyncSource是DispSync的监听者,有两个DisplaySyncSource对象,分别代表SF和APP的DisplaySyncSource,两个回调的Vsync时间不同.
4:DisplaySyncSource收到Vsync事件后,会发给他自己的监听者EventThread
notes: 给app vsync先于surfaceflinger,因为需要先画后合成----------------------------需要一个流程图

vsync 三缓冲参见: https://blog.csdn.net/a740169405/article/details/70548443
vsync源码实现:https://www.cnblogs.com/blogs-of-lxl/p/11443693.html 这个简单功能也要5个线程

surfaceFlinger摘要相关推荐

  1. Android图形系统篇总结摘要

    Android图形系统学习框架:Android图形系统 简单总结下Activity启动后布局显示过程: SurfaceFlinger 是在init.rc解析的时候被创建的,执行其main方法,实例化了 ...

  2. 图像零交叉点,视频生成,视频识别,视频摘要,视频浓缩

    图像零交叉点,视频生成,视频识别,视频摘要,视频浓缩 一.视频生成,视频识别,视频摘要,视频浓缩 视频生成与视频识别 视频分析的两大任务,前者侧重于对下一帧的预测,而前者则侧重于视频内容的理解.由于视 ...

  3. 3D目标检测论文阅读摘要

    3D目标检测论文阅读摘要 2D Object Detection 的研究已经非常成熟了,代表作品有RPN系列的FasterRCNN,One Shot系列的YOLOv1-YOLOv3,这里推荐一个2D ...

  4. 一篇论文摘要计算机英语,推荐:计算机毕业论文英文摘要的写作方法

    由于计算机专业本.专科的毕业生的论文中,对英文摘要的要求不是很高,所以下面的观点你可以根据具体需要进行借鉴. 一般的中文科技论文所附的英文摘要,其内容包含题名.摘要及关键词.GB 7713-87规定, ...

  5. ssm radis mysql_从零开始搭建框架SSM+Redis+Mysql(一)之摘要

    从零开始搭建框架SSM+Redis+Mysql(一)之摘要 本文章为本人实际的操作后的回忆笔记,如果有步骤错漏,希望来信307793969@qq.com或者评论指出. 本文章只体现过程,仅体现操作流程 ...

  6. c语言课程设计的摘要,投票程序设计-C语言课程设计摘要.doc

    投票程序设计-C语言课程设计摘要.doc C 语 言 课 程 设 计 题 目: <7>投票程序 设 计 者: 专 业: 班级学号: 所属院系:机电学院 指导教师: 2010年7月17日 1 ...

  7. btf-raft共识算法_了解Raft共识算法:学术文章摘要

    btf-raft共识算法 by Shubheksha 通过Shubheksha 了解Raft共识算法:学术文章摘要 (Understanding the Raft consensus algorith ...

  8. 软件可读性和效率取舍_网络通信设计中的一些限制和取舍:摘要

    软件可读性和效率取舍 by Shubheksha 通过Shubheksha 网络通信设计中的一些约束和折衷:摘要 (Some Constraints and Trade-offs In The Des ...

  9. 2018-3-25论文(Grey Wolf Optimizer )以及(The Whale Optimizer Algorithm)笔记一 -----作者网站+两论文摘要比对比

    论文来源: Seyedali Mirjalili http://www.alimirjalili.com/Projects.html 这两篇论文都是该作者发的分别是2016(WOA鲸鱼优化算法)和20 ...

最新文章

  1. 访问动态页面很慢 PHP,PHP动态网页程序优化及高效提速问题
  2. 无锁链表的c++实现
  3. java如何arraylist_Java如何使用ArrayList类?
  4. python如何计算个人gpa_使用While循环(Python)计算GPA
  5. Request.ServerVariables
  6. C#学习笔记(十一):动态类型
  7. Android 常见adb命令
  8. mac 遇到的奇怪问题?
  9. How To Fix: SCP And SSH Login Prompt Is Very Sl...
  10. 哈哈哈,看着问题一个个解决,很有满足感哦
  11. iPhone苹果手机iOS14更新升级到iOS15需要多久?
  12. jade选峰之后怎么去掉_jade使用教程
  13. 【计算机组成与结构】中央处理器
  14. vm12装xp系统步骤
  15. 被遗忘的艺术——图思维方式
  16. asterisk拨号规则
  17. abaqus导出全部节点应力值
  18. ubuntu22.04图文安装流程
  19. Js中两个等号(==)和三个等号(===)的区别
  20. Cf#741-C. Rings(构造)

热门文章

  1. Python 爬虫 Request(请求头)和Response(响应头)的 内容详解 【爬虫资料二】
  2. 音视频通话系统/企业级私有化部署视频会议系统EasyRTC-MCU进入会议室画面闪烁问题修复
  3. 你想怎样工作?平淡无奇还是激情四射?
  4. 学计算机的大学生用什么笔记本好,上大学该买电脑吗?学长:买的时候以为是刚需,买了变成“鸡肋”...
  5. 怎么解决?8007007e 找不到指定的模块
  6. SugarCRM CE 部署除错
  7. 基础的pdf病毒木马
  8. 计算机一级考试B十类理论题,计算机一级考试试题
  9. Django+Vue,前后端分离,实现用户权限认证
  10. BPG边界网关协议知识(一)