Android 14 - 绘制体系 - 概览

从Android 12开始,Android绘制系统有结构性变化, 在绘制的生产消费者模式中,新增BLASTBufferQueue,客户端进程自行进行queue的生产和消费,随后通过Transation提交到SurfaceFlinger,如此可以使得各进程将缓存提交到SufrfaceFlinger后合并到同一事务后同步提交,在同一帧生效。实际上,从Android12到Android14整个绘制系统各个环节也都或大或小调整,比如Android13发布了1.3版本的Vulkan, Android14新增了TextureView,等等。本文基于Android14

Android 绘制系统整体架构:

从上到下可以理解为“生产者(Producer)”到“消费者(Consumer)”处理过程

首先WindowManagerService角度每个窗口称为Window一个Window一般一个APP页面或者Status Bar或者Navigation Bar或者WallPaper这些一个个Window。WindowManagerService(WMS)作为服务端对所有客户端窗口添加、层级、布局等进行统一管理WMS每个Window对应一个SurfaceSurface可以理解图像数据缓存持有者以及Canvas持有者Canvas画布提供绘制各种图形能力供开发使用。一个客户端窗口在建立之初,会先向WMS去申请一个SurfaceWMS创建Surface之后,通过binder返回客户端客户端Surface后,会去创建一个BLASTBufferQueue管理图像内存申请每次要使用Surface的Canvas进行绘制前,需要BLASTBufferQueue申请一块内存(dequeue),我们这里称为Buffer,然后生成图像数据写入Buffer。这个向BLASTBufferQueue申请Buffer并写入图像数据的过程,可以认为是“生产”阶段。随后,enqueue这个buffer,将其提交SurfaceFlinger去合成。这个阶段可以理解图像Buffer的“消费”阶段

SurfaceFlinger(SF负责Hardware沟通维护着设备挂载、VSync信号收发、Layer合成工作。WMS每个SurfaceSurfaceFlinger对应生成一个Layer对象客户端将某个Surface上的Buffer提交SurfaceFlinger,实际上就是更新对应LayerBuffer数据SurfaceFlinger调用HWComposer将这些Layer进行合成显示屏幕

AndroidHAL提供称为一个Hardware Composer组件用于隔离具体硬件的交互。Hardware Composer简称HWComposerHWC2(之所以2早期已有一个HWC版本支持软件合成)。SurfaceFlingerLayer数据交给HWComposer,各厂商来负责HWComposer合成接口具体实现合成完毕数据提交屏幕设备缓存(一般称为Frame Buffer)屏幕显示画面

上面过程可以拆解为几部分

  1. Surface创建与管理
  2. 客户端(EndPoint)绘制(Draw)渲染(Render)图像
  3. 第三部分是硬件Composition(合成)工作
  4. Vsync:由硬件产生信号用于同步framebuffer生产消费SurfaceFlingerVsync进行使用管理向上分发APPVsync是不断绘制驱动力,也是图像缓存有序投送到屏幕的重要机制。

现在分别讨论下四部分

  1. Surface的创建与管理

Surface创建过程中有几个角色贯穿其中

PhoneWindow一个Activity对应一个PhoneWindow代表一个应用窗口AMS创建Activity之初PhoneWindow服务端对应window对象(ActivityRecord)已经添加WMS

ViewRootImpl:其主要作用服务端通信承接外部触发绘制调用从而从上往下整个View树进行绘制可以把ViewRootImp理解为View的调度者ViewRootImp逻辑上View Hierarchy最顶层并不是一个真正View持有一个View--DecorViewDecorView才是真正ViewView最上层,包含着Activity的画面内容。在Activity的resume阶段,ViewRootImplrelayout方法会将DecorView添加到WMS中,这样Activity的内容就显示了出来。逻辑上,我们可以把DecorView也理解为一个Window。Activity对应一个PhoneWindow,通过ViewRootImplDecorView在WMS端添加PhoneWindowWindow。

WMS的Session客户端一个进程对应WMS一个Session客户端持有Sessionbinder客户端窗口添加事务客户端都是通过这个SessionWMS通信

WindowContainerWMS管理系统整体Window体系包括位置层级关系通过WindowContainer这个表达一个WindowDisplayContent代表一个屏幕级别WindowDisplayArea代表一块屏幕一块区域比如平板等大屏幕设备可能一块屏幕上同时显示多个应用区域此时就用DisplayArea表达WindowToken简单理解为对应一个客户端Window比如一个应用Activity,这里需要注意的是,Activity的WindowToken是作为ActivityRecord存在的,也就是说ActivityRecord是WindowToken的子类。而Activity具体内容承载者,DecorView对应WindowState上面所有DisplayContentDisplayAreaWindowTokenWindowState都是WindowContainer子类,这些Window在WMS内是以window树的形式组织起来的。事实上DisplayContent下面还有一个层级称为Feature具体层级结构Android12 - WMS之WindowContainer树(DisplayArea)_android windowcontainer-CSDN博客客户端通过Session接口调用添加DecorViewWMS生成一个对应WindowState对象将其作为Activity对应ActivityRecord(也就是WindowToken)window

SurfaceControl:在WMS端,每个WindowContainer对应一个SurfaceControlSurfaceControlWMS端管理Surface具体对象,在WMS端,可以理解一个SurfaceControl就代表一个Surface。SurfaceControl在SurfaceFlinge端对应一个Layer,持有一个layer的句柄handle。所有绘制动作最后提交SurfaceFinger作为Layer去合成。SurfaceControl作用或者Surface作用主要客户端窗口SurfaceFlingerLayer关联起来客户端Add一个DecorView WMS对应创建WindowState同时创建一个SurfaceControl、Layer随后SurfaceControl返回客户端客户端拿到SurfaceControl之后转换成Surface后续绘制就在这个Surface进行

SurfaceComposerClient是一个Binder主要作用是SurfaceControl调用SurfaceFlinger过程中,作为一个通道角色由于SurfaceControlWMS客户端持有所以客户端WMS都可以通过这个通道调用SF比如Layer创建、Graphihc Buffer提交

1. 客户端绘制和渲染

客户端通过Surface中提供的Canvas进行绘制Canvas基于Skia的SKCanvas。Skia(https://skia.org/)是Google管理的开源2D(也可以支持3D)图像库,目前AndroidGoogle ChromeChromeOS、Mozilla FireFoxFireFoxOS使用Skia作为绘制引擎。Skia可以集成OPEN GL和Vulkan进行3D绘制Android Q以后Skia作用加强即使硬件加速场景中绘制也会封装成Skia的GrOpList再提交给GPU。Android 14 Skia目录external/skia

渲染的过程是将画好的图像,进行栅格化(Rasterizer),变成一个个像素,这是一个非常耗时的过程。Android 3以前支持软件渲染Software Render过程如下:

APPViewonDraw阶段使用Canvas绘制通过Skia进行软件栅格化,通过CPU计算,将绘制内容转化成一个个像素信息,随后投送给屏幕进行显示。由于软件渲染效率低,当下软件渲染只是作为兼容方案得以保留,默认使用硬件加速。

硬件加速的流程简单表述如下:

Android硬件加速相关能力封装hwui组件hwui地址platform/frameworks/base/libs/hwui

硬件加速模式下APPonDraw通过Canvas绘制内容最终封装DisplayList一个个GrOp绘制命令然后通过OpenGL或者Vulkan交由GPU进行渲染随后结果投送屏幕显示具体使用OpenGL还是Vulkan可选择早期Android使用OpenGL由于Vulkan支持多线程渲染性能方面优势Android逐渐倾向使用Vulkan进行渲染另外,在哪些维度上进行硬件加速也是可选

整体使用硬件加速情况如果某个View绘制暂时不支持硬件加速,或者在某些位移动画上为了减少渲染成本,可以动过设置ViewlayerType = LAYER_TYPE_SOFTWARE单纯某个特定View使用Software Render。

硬件加速除了利用GPU加速渲染效率 本身计算渲染范围相较软件渲染更加高效软件渲染每次更新一个View局部将使得整个View hierarchy重新渲染硬件加速标注变化部分,所谓damage area,将绘制指令保存DisplayList中,如此大大提高渲染速度

OpenGL ES VS Vulkan

以下OpenGL ESVulkanAndroid发布版本历史

Vulkan作为一个面向更低级别规范、跨平台的API,可以提供更细粒度的内存管理和资源管理

以下VulkanOpenGL ES使用率(from GDC 2023 https://www.youtube.com/watch?v=C7OjI7CpjLw&t=1188s):

对于未来计划OpenGL ES将不会再有功能更新功能只会Vulkan支持因此Vulkan未来Android主推渲染引擎

无论OpenGL还是Vulkan都需要GPU的支持例如常见的车载高端芯片高通8155明确标明支持: OpenGL ES 3.xVulkanhttps://www.qualcomm.com/content/dam/qcomm-martech/dm-assets/documents/qul7413_sa8155_productbrief_r4.pdf

2. HW Composer(HWC2)图像合成

前面提到过,每个window对应一个SF中的Layer合成(Composition)工作就是这些Layer进程合并一个完整屏幕内容提交给硬件屏幕显示出来大概过程如下

页面LayerStatusBarNavigationBar中间APP内容页面,其中可能会有重叠的部分,称为Overlay。Composition工作就是将这三个Layer合并一个画面,计算重叠部分的颜色,提交屏幕显示出来

合成工作发生在渲染后的内容提交给SurfaceFlinger之后。大致流程如下

合成硬件合成的部分软件合成部分。硬件合成除了更高效的同时,可以合成工作GPU解放出来,提高GPU效率,节省能耗。嵌入式设备的SOC中,硬件合成一般独立DPU(Display Processing)完成

比如高通SA8155这款SOC布局如下

其中GPU部分负责渲染,“Dispay Processing”的部分用来处理合成工作

由于硬件合成Layer数量是限制例如高通QCS2290支持4个Layer、AMD有的芯片支持7)以及Layer的PixelFormat(比如支持PIXEL_FORMAT_RGBA_8888不支持YUV)是限制的,因此硬件合成之前如果合成Layer过多或者Format不满足需要使用GPU先进行一轮软件合成合并或转换一些Layer格式

软件合成过程。(Google I/O '18)

4. VSYNC

VSync简介:

首先关注两个重要概念

refresh rate - 60Hz 代表每秒钟屏幕可以更新多少次这一值早期是固定依赖于硬件现代旗舰设备屏幕支持多个刷新率60Hz~165Hz不等而且是可以App定制刷新率

frame rate秒钟GPU可以绘制多少越大越好

VSync一个通用概念LinuxPC移动设备实现

想象一下绘制过程是这样的:GPU绘制数据,将绘制结果投掷给屏幕显示出来

问题是refresh rateFrame Rate并不保证一致频率,也就是是说GPU渲染的时间并不能保证就正好是16ms(60Hz)内完成的。如果只有一块内存(Frame Buffer)用来交换数据,假如Refresh Rate大于Frame Rate由于GPU从上到下写这块内存的在当屏幕来取数据的时候,GPU刚刚在旧基础上一半此时就会出现图片撕裂问题

解决方法是双缓存方案

提供Back Buffer和Frame Buffer两个缓存,屏幕始终Frame Buffer数据显示GPU往Back BufferGPU完全数据写好Back Buffer整个拷贝Frame Buffer这样就能保证屏幕每次完整

此时仍有一个问题如果GPU的Frame Rate大于屏幕Refresh Rate那么屏幕下一可能GPU写完好几就会出现丢帧现象此时就需要VSync

屏幕根据自己的刷新频率,去给上层发送一个VSync信号GPU拿到这个VSync信号绘制这样就能同步屏幕上层绘制节奏

如果屏幕Refresh Rate大于GPUFrame Rate怎么

屏幕将会仍然显示旧帧。比如中间方框两次刷新屏幕仍然显示前一次内容

Android的VSYNC

实际上Android的VSync要复杂得多,主要由SurfaceFlinger负责实现。通过之前的介绍我们知道一帧的绘制过程有APP绘制渲染SurfaceFlinger合成Display硬件读取帧缓存显示图片三个阶段,如果每一个阶段都依赖VSync信号来执行,那可能会出现这种情况:

也就是VSync1时候APP正在绘制渲染SF还没有可以合成东西所以什么不做等到VSync2时候Render1工作已经完成可以合成VSync3时候合成做完了才可以显示屏幕上绘制渲染显示经历3VSync面对这种情况AndroidVSync设计如下

有三种信号

HW_VSYNC_[ID]底层硬件按Refresh Rate的频率发出,一般为60Hz、90Hz、120H等等,随后会通过HWC通知SurfaceFlinger

VSYNC-app:SurfaceFlinger通知给上层应用VSYNC用于控制和驱动应用绘制渲染

VSYNC-sf:通知给SurfaceFlinger自身的,用于合成Layer信号

VSYNC-appVSYNC-sfHW_VSYNC_[ID]并不是同步发送而是有一定延迟,称为相位差HW_VSYNC_[ID]VSYNC-app发出时间差称为app phaseHW_VSYNC_[ID]VSYNC-sf发出时间差称为sf phase这种设计好处是如果同一个VSync周期内,经sf phase后在执行合成时恰好前一步Render完成就可一个周期完成不用非得下一个VSync

另外Android并非直接硬件HW_VSYNC_[ID]信号直接分发应用SurfaceFlinger而是通过先收集HW_VSYNC_[ID]样本,再根据屏幕Refresh Rate、预先配置的相位差等信息,经过计算模拟出来VSYNC-appVSYNC-sf

由于只需要一定的硬件VSync样本便可以模拟出预期VSYNC-appVSYNC-sf因此并不需要一直HW_VSYNC_[ID]信号收到足够样本(在Android 14中为6个)就可以关闭硬件VSync每次合成数据提交屏幕返回一个硬件VSync时间戳(PresentFence),此时SF对比当前模拟VSync硬件VSync是否误差过大如果过大重新打开硬件VSync收集样本重新计算另外每次终端应用主动请求VSync判断前后两次模拟VSync时间差是否超过750ms如果重新请求打开硬件VSyncsystrace硬件VSyncTAGHW_VSYNC_ON_[ID]

参考资料https://source.android.com/docs/core/graphics/implement-vsync

可变刷新率

现代旗舰机屏幕刷新率可变,比如Pixel 5:

可以看到屏幕是支持60Hz90Hz两种刷新率

而且应用层可以在应用级别、窗口级别指定具体刷新率经过应用指定最终刷新率并不一定指定而是经过SurfaceFlinger综合计算得出具体见https://developer.android.com/media/optimize/performance/frame-rate

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/653543.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

N的阶乘(高精度)

目录 题目描述 输入格式 输出格式 样例输入 样例输出 思路 参考代码 题目描述 输入正整数n,输出n! 输入格式 一个正整数n,n 3000 输出格式 输出n! 样例输入 3 样例输出 9 思路 主要就是高精度乘法的模版&#x…

电脑中msvcp100.dll丢失了怎么办?总结7种靠谱的解决方法

msvcp100.dll 文件是 Microsoft Visual C 2010 Redistributable 的一部分,这是一个重要的动态链接库(DLL)文件,用于存储许多程序共同使用的代码和资源。它是执行 C 编写的应用程序所必需的,尤其是那些使用 Visual C 20…

太极图形学——渲染——光线追踪概念部分

程序动画和渲染 程序动画和渲染有一些类似的地方,都是找到合适的像素并填上颜色,但是要把一个图片渲染的好看是有一些规则来指导的 光线追踪包含哪些呢 果壳中的光线追踪器 实时条件下的光线追踪:需要进行光栅化的处理 离线条件下做cg的话…

一文了解知识中台:是什么、作用、如何搭建

在当今信息繁杂的时代,知识对于企业来说犹如宝藏般重要,而知识中台就是宝藏山的藏宝图。关于知识中台,你可能会感到好奇,它究竟是什么,有什么作用,又该如何搭建知识中台呢?接下来就让LookLook同…

假如有几十个请求,如何去控制高并发?

公司项目中做图片或文件批量下载,每次下载都是大批量的,那么假如我一次性下载几十个,如何去控制并发请求的? 让我想想,额~, 选中ID,循环请求?,八嘎!肯定不是那…

虚拟机报错:VMX 进程已提前退出。VMware Workstation 无法连接到虚拟机。

解决报错:VMware Workstation 无法连接到虚拟机。请确保您有权运行该程序、访问该程序使用的所有目录以及访问所有临时文件目录。 VMX 进程已提前退出。 解决方案:右键桌面图标进入VMware Workstation Pro的属性设置,兼容性–勾选“以管理员…

Java解析并修改JSON:将isShow属性改为false

哈喽,大家好,我是木头左! 在Java中,可以使用各种库来处理JSON数据。其中,Jackson和Gson是两个非常流行且功能强大的库。在这篇文章中,将使用Jackson库来解析给定的JSON字符串,将其转换为Map对象…

大学运动康复试题及答案,分享几个实用搜题和学习工具 #其他#职场发展

大学生除了学习专业知识外,还应该关注和学习一些软技能,如沟通能力、团队合作和领导力等,以提升自己的综合素质。 1.滴墨书摘 这款软件相当于一个在线“摘抄本”,我们可以利用它来记录一些阅读时遇到的好句子或者是段落&#xf…

“揭秘:为什么羊驼Ollama成为计算机运行大型语言模型的最佳拍档?“

最近,AIM 评测了在计算机上本地运行大语言模型(LLM)的最佳工具,Ollama 脱颖而出,成为最高效的解决方案,提供了无与伦比的灵活性。Ollama 是 Jeffrey Morgan 开发的一款开源工具,它正在彻底改变爱…

【源码】2024心悦搜剧源码百万级网盘资源

1、一键转存他人链接:就是将别人的分享链接转为你自己的 2、转存心悦搜剧资源:就是将心悦搜剧平台上的所有资源都转成你自己的 3、每日自动更新:自动转存每天的资源并入库 前端uin-app,后端PHP,兼容微信小程序

vscode+docker搭建迷你开发环境。制作docker镜像,并通过vscode连接后进行开发

制作自己的docker镜像,将docker镜像作为服务器,接受vscode连接 目录 1. 制作开发环境镜像 1.1 选择基础镜像 1.2 编写dockerfile 1.3 构建镜像 2. 启动镜像 3. 添加用户 3.1 查看物理机上用户信息 3.2 登录到docker中 3.3 按照物理机的用户和组…

如何搭建雾锁王国多人联机服务器,搭建教程分享

雾锁王国(Enshrouded)是一款融合了生存、制作以及动作RPG战斗的游戏,2024年1月24日在Steam平台以抢先体验形式发售,支持中文。游戏背景设定在一个基于体素构筑的辽阔大陆上。玩家将在这个开放世界中自由选择前进的方向&#xff0c…

Linux-CentOS7-解决vim修改不了主机名称(无法打开并写入文件)

Linux-CentOS7-修改主机名称 修改之后使用强制保存退出也不行。 解决办法: 使用hostnamectl命令进行修改 查看系统主机名和信息: hostnamectl这条命令会显示当前系统的主机名、操作系统信息、内核版本、架构信息等相关信息。 修改系统主机名&#xff1…

力扣算法之1070. 产品销售分析 III

力扣传送门 题解 选出每个售出过的产品 第一年 销售的 产品 id、年份、数量 和 价格,很明显就是个排序问题 我的解 SELECT product_id,year as first_year,quantity,price FROM ( SELECT sale_id,RANK() OVER(PARTITION BY product_id ORDER BY [year] asc ) A…

软件测试人员如何规划自己的职业发展路线

在这个飞速发展的时代中,我们每个人都渴望在各自的领域里找到属于自己的一片天空,而对于那些致力于软件测试的朋友们而言,规划好自己的职业发展路线显得尤为重要。 一、明确目标 首先,我们需要确立一个明确的职业发展目标。对于软…

【Spring Cloud】API网关

目录 什么是API网关为什么需要API网关前言问题列表 API网关解决了什么问题常见的网关解决方案NginxLuaSpring Cloud Netflix ZuulSpringCloud Zuul的IO模型弊端 Spring Cloud Gateway 第二代网关——GatewayGateway的特征Spring Cloud Gateway的处理流程Spring Cloud Gateway的…

将 MAX30100 脉搏血氧仪与 Arduino 连接

在这个项目中,我们将MAX30100 脉搏血氧仪传感器与 Arduino 连接起来。MAX30100 传感器能够测量血氧和心率。我们可以使用任何显示器(如162 LCD 显示器)来查看SpO2和BPM的值。血氧浓度(称为 SpO2)以百分比为单位测量&am…

在今日头条上写文章:ChatGPT完整使用教程

了解如何充分运用ChatGPT进行创作 简介 在今日头条上发布文章变得越来越方便。本文旨在详细解析如何运用ChatGPT来创作文章,并提供全方位的使用指南及常见问题的答疑。 第一步:基础准备 确保你已注册今日头条账号。 登录ChatGPT并与你的今日头条账号进…

Python 应用开发:Streamlit 布局篇(容器布局)

st.columns 以并列方式插入容器。 插入若干并排排列的多元素容器,并返回一个容器对象列表。 要在返回的容器中添加元素,可以使用 with 符号(首选)或直接调用返回对象的方法。请参见下面的示例。 列只能放置在其他列的内部&…

想用Python做OCR?看看这篇文章

OCR是Optical Character Recognition的缩写,中文名为光学字符识别。它是一种通过计算机技术对图像或扫描文档中的文字进行识别和理解的过程。OCR技术可以将图像中的文字转换为可编辑、可搜索的文本,使得计算机能够理解和处理这些文字信息。 OCR技术通常…