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

Android GPU渲染屏幕绘制显示基础概念(1)

Android GPU渲染屏幕绘制显示基础概念(1)

 

Android中的图像生产者OpenGL,Skia,Vulkan将绘制的数据存放在图像缓冲区中,Android中的图像消费SurfaceFlinger从图像缓冲区将数据取出,进行加工及合成。

SurfaceFlinger是Android最重要的图像消费者,Activity绘制的界面,都会传递到SurfaceFlinger,SurfaceFlinger的作用是接收图像缓冲区数据,然后交给HWComposer或者OpenGL做合成。

SurfaceFlinger是如何接收图像缓冲区的数据呢?先了解Layer(层)概念,一个Layer包含一个Surface,一个Surface对应一块图形缓冲区,而一个界面是由多个Surface组成的,所以它们会一一对应到SurfaceFlinger的Layer中。SurfaceFlinger通过读取Layer的缓冲数据,就相当于读取界面上Surface的图像数据。

f6311d4ad8a746239681165015c398af.webp

图像数据→CPU→显卡驱动→显卡(GPU)→显存(帧缓冲)→显示器

App绘制及SF的合成分别由对应的软件VSYNC驱动:VSYNC-app驱动App绘制;VSYNC-sf驱动SF进行合成。
VSYNC-app与VSYNC-sf按需发射,如果App要更新界面,它申请VSYNC-app,如果没有App申请VSYNC-app,那么VSYNC-app不发射。同样,当App更新界面,它会把对应的Graphic Buffer放到Buffer Queue中。Buffer Queue通知SF进行合成,此时SF申请VSYNC-sf。如果SF不申请VSYNC-sf,VSYNC-sf将不再发射。如果App持续不断的更新,它就得不断申请VSYNC-app;而对SF来说,只要有合成任务,它就得再去申请VSYNC-sf。Choreographer 可以接收系统的 VSYNC 信号,统一管理应用的输入、动画和绘制等任务的执行时机

VSYNC-app与VSYNC-sf相互独立。VSYNC-app触发App绘制,Vsync-sf触发SF合成。App绘制与SF合成都会加大CPU负载,为避免绘制与合成造成性能问题,VSYNC-app可与VSYNC-sf稍微错开。

  • Vsync offset机制: Vsync-app、Vsync-sf并不是同时通知的,Vsync-sf相对晚些,但对于App来说,可认为大约同时发生。

硬件VSYNC同步信号发送周期是固定的,既然都相互独立在自己进程里等待VSync信号到来,然后各司其职做自己的工作,那通过更改偏移量的方式把“APP进程”和“sf进程”接收到VSync信号的时间错开就可以实现:在一个硬件VSync信号周期内完成“渲染”和“合成”两件事,具体方案如下:

VSyncPhaseOffsetNs = 0,硬件VSync发生后,直接转发给app进程,让它开始绘制;
sfVSyncPhaseOffsetNs ≥1,硬件VSync发生后,延迟几毫秒再转发给sf进程,因为app已经渲染完成,sf合成刚刚渲染的图层;
好了,在一个硬件VSync周期(如熟知的16ms)内“渲染”和“合成”的工作都已经完成了,并且由于GPU性能过于快速,距离下次硬件VSync信号发送甚至还有14ms...等下一次硬件VSync信号到来时,显示框架完成,画面切换,和之前的方案比,同样是60HZ的屏幕,用户从按下按钮到看到画面更新,只需要等待1个VSync信号周期,也就是约16ms。

6f47c5129abf4a298fafadd2849a4ed9.png

SF合成的是App的上一帧,而App当前正在绘制的那一帧,要等到下一个VSYNC-sf来临再进行合成。Choreographer用于实现CPU/GPU的绘制是在VSYNC到来时开始。

GPU(Graphics Processin Unit,图形处理器),是一种专门用于图像运算的处理器,在计算机系统中通常被称为 "显卡"的核心部件就是 GPU。

2653b93885ae4a43a90f4d1569bb94d6.webp

 

UI 组件在绘制到屏幕之前,都需要经过 Rasterization(栅格化)操作,而栅格化又是一个非常耗时的操作。Rasterization 栅格化是绘制那些 Button、Shape、Path、String、Bitmap 等显示组件最基础的操作。栅格化将这些 UI 组件拆分到显示器的不同像素上进行显示。这是一个非常耗时的操作,GPU 的引入就是为了加快栅格化。

Android APP而言,GPU硬件加速绘制可以分为:

第一阶段:APP在UI线程构建渲染的命令及数据.
第二阶段:CPU将数据上传(共享或者拷贝)给GPU,PC一般有显存,但ARM嵌入式设备内存一般是GPU-CPU共享内存.
第三阶段:通知GPU渲染,CPU一般不会阻塞等待GPU渲染结束,效率低,CPU通知结束后就返回继续执行其他任务,Fence辅助GPU CPU同步.
第四阶段:swapBuffers,通知SurfaceFlinger图层合成.
第五阶段:SurfaceFlinger合成图层,如果之前提交的GPU渲染任务没结束,则等待GPU渲染完成,再合成(Fence机制),合成依然是依赖GPU,不过这作为下一个任务.

第一阶段主要是CPU工作,这个阶段前期运行在UI线程,后期部分运行在RenderThread(渲染线程),第二个阶段主要运行在渲染线程,CPU将数据同步(共享)给GPU,之后,GPU进行渲染,CPU一般不会阻塞等待GPU渲染完毕,而是通知结束后就返回。CPU返回后,会直接将GraphicBuffer提交给SurfaceFlinger,告诉SurfaceFlinger进行合成,但是这个时候GPU可能并未完成之前的图像渲染,这时候就牵扯到一个同步,Android中,用的是Fence机制,SurfaceFlinger合成前会查询Fence,如果GPU渲染没有结束,则等待GPU渲染结束,GPU结束后,会通知SurfaceFlinger进行合成,SF合成后,提交显示,最终完成图像的渲染显示。

a73dbc500b5b47a9a725f331471a47e3.webp

GraphicBuffer是整个图形系统的核心,渲染操作都将在此对象上进行,包括同步给GPU和HWC,每当应用有显示需求时,应用会向系统申请一块GraphicBuffer内存,这块内存将会共享给GPU用于渲染工作,接着会同步给HWC用于合成和显示,可以把每一个GraphicBuffer对象看做是一个个渲染完成的图层。

在Android里,GraphicBuffer的同步主要借助Fence同步机制,最大特点是能处理GPU、CPU、HWC的同步。GPU处理一般是异步的,CPU命令并不是即刻被GPU执行的,而是被缓存在缓冲区中,而CPU可能不知道执行时机,除非CPU阻塞等待,但毫无疑问会使CPU、GPU并行处理效率降低,至少,渲染线程是被阻塞,所以,CPU提交命令后就返回,不等待GPU处理。SurfaceFlinger图形合成,SurfaceFlinger需要知道什么时候GraphicBuffer被GPU处理填充完毕,这个时候就是Fence机制发挥作用的地方。

一个GraphicBuffer对象的生命周期:

渲染阶段:应用有绘图需求了,系统分配一块内存给应用,应用调用GPU执行绘图,此时使用者是GPU。
合成阶段:GPU渲染完成后将图层传递给sf进程,sf进程决定由谁来合成,hwc或者GPU,如果使用GPU合成,那么此时GraphicBuffer的使用者依旧是GPU,如果使用hwc合成,那么此时GraphicBuffer的使用者是hwc。
显示阶段:所有的GraphicBuffer在此阶段使用者都是hwc,因为hwc控制着显示芯片。
从生命周期可以看出GraphicBuffer对象在流转的过程中,会被GPU、CPU、DPU三个不同的硬件访问。如果同一块内存能够被多个硬件设备访问,就需要一个同步机制,Android图形系统中,Fence机制就是用来不同模块访问时的数据安全,Fence的逻辑实现可参考Java的synchronized互斥锁,可把Fence理解为一把硬件的互斥锁,每个需要访问GraphicBuffer的角色,在使用前都要检查这把锁是否unlock了才能进行操作,否则就要等待(waitForever)。

BufferQueue

它是一个封装了GraphicBuffer的队列,BufferQueue对外提供了GraphicBuffer对象出列/入列的接口。BufferQueue生产者/消费者模式,大多数情况,APP作为GraphicBuffer的生产者,sf进程作为GraphicBuffer的消费者,共同操作一个buffer队列。

生产者:APP进程

1、producer->dequeueBuffer()

​ 从队列取出一个状态为“FREE”的buffer,此时该buffer状态变化为:FREE->DEQUEUED

2、producer->queueBuffer()

​ 将渲染完成的buffer入列,此时该buffer状态变化为:DEQUEUED->QUEUED

消费者:sf进程

1、consumer->acquireBuffer()

​ 从队列中取出一个状态为“QUEUED”的渲染完的buffer准备去合成送显,此时该buffer的状态变化为:QUEUED->ACQUIRED

2、consumer->releaseBuffer()

​ buffer内容已经显示过了,可以重新入列给APP使用了,此时该buffer的状态变化为:ACQUIRED->FREE

每个Buffer的一生,就是在不断地循环FREE->DEQUEUED->QUEUED->ACQUIRED->FREE这个过程,这中间有任何一个环节出现延迟,反应到屏幕上就是应用出现了卡顿。

无论App使用哪种API进行图形开发绘制,在绘制流程结束后,APP作为图层的生产者总是会调用BufferQueue的queueBuffer()方法将GraphicBuffer入列,一旦有新的图层加入队列,就意味着作为图层消费者的SF进程可以开始工作了。

当APP端的Surface发生变化以后,Layer的onFrameAvailable()方法会被调用,经过层层转发,最终由MessageQueue#requestNextVSync()执行VSync信号的请求。
APP进程中的每一个Surface对象,对应SF进程当中的一个Layer对象,它俩共享一个BufferQueue,
Surface作为图层的生产者,封装了出列入列的操作,
Layer作为图层的消费者,封装了获取渲染图层和释放图层的操作。

 

一个APP完整的显示流程大致分为三个阶段
app-请求
APP页面元素一旦发生变化,调用invalidate()/requestLayout()方法请求下一次VSync信号,此时sf什么都不做。
app-VSync & sf-请求
app-VSync信号到来后,APP进程执行绘图三部曲,绘图流程结束后,sf收到onFrameAvailable(),sf进程请求VSync。
sf-VSync
sf-VSync信号到来,sf进程执行合成,接着将结果提交给hwc,等待下次硬件VSync信号发生,切换Framebuffer展示给用户。

 

 

 

 

Android性能:Double Buffer双缓冲/Triple Buffer三缓冲丢帧Jank与无丢帧No Jank-CSDN博客文章浏览阅读850次,点赞6次,收藏13次。Android ADB调试真机设备Android ADB(Andorid Debug Bridge),是Android开发中有用的测试和调试工具。使用Android ADB调试设备,直接在Windows的dos命令窗口输入命名adb即可,如图:为什么执行adb命令后是这样?_android 抓trace。三Buffer轮转情况下,基本不会有这种情况的发生,渲染线程一般在 dequeueBuffer 时,都可以顺利拿到可用的 Buffer (如果 dequeueBuffer 本身耗时那就也会拉长时间)。https://blog.csdn.net/zhangphil/article/details/138213964

 

相关文章:

Android GPU渲染屏幕绘制显示基础概念(1)

Android GPU渲染屏幕绘制显示基础概念(1) Android中的图像生产者OpenGL,Skia,Vulkan将绘制的数据存放在图像缓冲区中,Android中的图像消费SurfaceFlinger从图像缓冲区将数据取出,进行加工及合成。 Surface…...

Mac电脑设置hosts的方法

hosts文件是什么 hosts文件是一个系统文件,通过绑定域名与ip的关系,当本机访问该域名时 从这个文件中如果找到了对应域名,则转发到对应ip;如果没有找到对应域名,则走默认的DNS公网解析。 好处: 加速访问…...

数据分析——大数据伦理风险分析

大数据伦理风险分析 前言一、大数据伦理二、大数据技术伦理风险算法安全性、可信赖性及稳定性风险及其应对算法风险的表现算法风险的危害算法风险的应对 算法的可解释性风险及其应对算法可解释性风险的内容算法可解释性风险的损害算法可解释性风险的应对 算法的决策不可预见性风…...

漫谈AI时代的手机

以chatGPT 为代表的大语言的横空出世使人们感受到AI 时代的到来,大语言模型技术的最大特点是机器开始”懂人话“,”说人话“了。如同任何一个革命性工具的出现一样,它必将改变人类生活和工作。 在这里。我谈谈AI时代的手机。 语音通信的历史…...

fatal error: ros/ros.h: 没有那个文件或目录

解决方法: 在出错的文件的包下的CMakeLists.txt文件里,加上 find_package(catkin REQUIRED COMPONENTSroscpp )include_directories(include ${catkin_INCLUDE_DIRS} )【ROS-解决问题】 fatal error: ros/ros.h: 没有那个文件或目录-CSDN博客...

苍穹外卖Day06笔记(复习了jwt的加密解密和传递)

疯玩了一个月,效率好低,今天开始捡起来苍穹外卖~ 1. 为什么不需要单独引入HttpClient的dependency? 因为我们在sky-common的pom.xml中已经引入了aliyun-sdk-oss的依赖,而这个依赖低层就引入了httpclinet的依赖,根据依…...

【ARM 嵌入式 C 字符串系列 23.9 -- strcmp 与 strncmp 在使用上的区别以及注意事项】

请阅读【嵌入式开发学习必备专栏】 文章目录 strcmp 与 strncmp 使用介绍strcmpstrncmp使用建议 strcmp 与 strncmp 使用介绍 strcmp 和 strncmp 都是 C 语言标准库中用于比较两个字符串的函数&#xff0c;它们定义在 <string.h> 头文件中。这两个函数在功能上相似&…...

行列视(RCV):企业数据处理的革新工具

在当前数据驱动的商业生态系统中&#xff0c;行列视&#xff08;RCV&#xff09;系统以其创新的企业数据处理功能&#xff0c;不断地为各行各业的企业带来变革。行列视系统能够处理大规模数据集&#xff0c;支持多达400种Excel函数&#xff0c;使得数据处理不仅限于基本的表格操…...

Oracle Patch清理

场景&#xff1a; 在对Oracle安装补丁后&#xff0c;会发现OS上被占用了大量的空间&#xff0c;本文档清理Opatch过程中的一些文件&#xff0c;释放空间 参考文档&#xff1a; Can You Delete $ORACLE_HOME/.patch_storage Directory ? (Doc ID 403218.1) How To Avoid Disk …...

Redis-三主三从高可用集群搭建

正式搭建之前&#xff0c;注意事项&#xff08;坑&#xff09;提前放到最开始&#xff0c;也可以出问题回来看&#xff0c; &#xff08;1&#xff09;第二步中最好将配置文件中的logfile自定义一个目录&#xff0c;以便于在第五步中启动出错的时候迅速定位错误。 &#xff0…...

ImageMagick

Linux 安装 sudo apt install php8.2-imagick Windows 安装 下载 ImageMagick ImageMagick – Download 安装并将 D:\Program Files\ImageMagick-7.1.1-Q16-HDRI 加入到系统环境变量 path 中&#xff0c; 或者将 CORE_RL_*.dll 复制到 c:\windows\system32 下 下载 php 扩展…...

攻防世界-web-command_execution

题目&#xff1a; 原理&#xff1a; | 的作用为将前一个命令的结果传递给后一个命令作为输入 &&的作用是前一条命令执行成功时&#xff0c;才执行后一条命令 方法一&#xff1a; 第一步&#xff1a; 1.打开浏览器&#xff0c;在文本框内输入127.0.0.1 | find / -name…...

go语言自定义排序接口Interface实现示例 sort.Sort(data Interface) 快速排序 pdqsort

go语言sort.Sort(data Interface) 排序接口自定义排序实现&#xff0c;golang里面的sort包中的Sort方法底层使用的是 pdqsort的一个快速排序算法&#xff0c; 我们可以将要排序的对象实现Interface接口后直接丢个这个函数即可自动按照我们指定的方式进行数据快速排序。 sort函…...

RIP动态路由协议详解

目录 一&#xff1a;RIP协议的基本信息 二&#xff1a;RIP协议中的更新方式 三&#xff1a;RIP协议中的计时器 定时更新器&#xff08;UPDATE timer&#xff09; 无效定时器&#xff08;invalid Timer&#xff09; 垃圾收集定时器&#xff08;garbage collection timer&a…...

ROS2 安装与测试

文章目录 ROS2 安装与测试ROS2 安装1. 设置编码2. 添加源3. 安装 ROS24. 设置环境变量 ROS2 示例测试实例一&#xff1a;命令行实例实例二&#xff1a;小海龟仿真实例 参考链接 ROS2 安装与测试 ROS2 安装 基于 Ubuntu 22.04 LTS 操作系统。 1. 设置编码 sudo apt update &…...

MySQL数据分组技术深度解析及实践

在处理大量数据库记录时,数据分组是一种强大的工具,它允许我们按照特定列的值将数据划分为逻辑上的集合,进而对每个集合执行聚合操作,如计数、求和或平均值等。MySQL中的​​GROUP BY​​​子句正是实现这一功能的关键所在。本文将详细介绍​​GROUP BY​​的使用方法,结合…...

【敦煌网注册/登录安全分析报告】

敦煌网注册/登录安全分析报告 前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大…...

Python读取ASC文件并转换成Excel文件(坐标)

import pandas as pd# 读取asc文件&#xff0c;指定空格为分隔符 df pd.read_csv(out_view2.asc, sep , headerNone)# 去掉空列 df df.dropna(howall, axis1)# 将数据保存到Excel文件 df.to_excel(out_view2.xlsx, indexFalse, headerFalse)效果图...

Rust 的 Warp 库编写的 restful api 参数传递与解析方法

Warp是一个用 Rust 编写的流行的异步 web 框架。在使用 warp 构建 RESTful API 时&#xff0c;可以通过多种方式传递参数到你的处理函数中。 以下是一些常见的方法&#xff0c;说明如何在 warp 中传递参数&#xff1a; 路径参数&#xff1a; 你可以使用 warp::path 和 warp::…...

关不掉的弹窗

这里分两种方式 第一种 #include<Windows.h> int main(){system("mode 15,14");while(1){MessageBox(NULL,TEXT("关不掉吧!"),TEXT("中病毒啦~~你这个SB!"),MB_OK);}} 实际上不是关不掉&#xff0c;而是关不完 解决方法&#xff1a;找…...

Chapter03-Authentication vulnerabilities

文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...

反向工程与模型迁移:打造未来商品详情API的可持续创新体系

在电商行业蓬勃发展的当下&#xff0c;商品详情API作为连接电商平台与开发者、商家及用户的关键纽带&#xff0c;其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息&#xff08;如名称、价格、库存等&#xff09;的获取与展示&#xff0c;已难以满足市场对个性化、智能…...

在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能

下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能&#xff0c;包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地

借阿里云中企出海大会的东风&#xff0c;以**「云启出海&#xff0c;智联未来&#xff5c;打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办&#xff0c;现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...

视频字幕质量评估的大规模细粒度基准

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用&#xff0c;因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型&#xff08;VLMs&#xff09;在字幕生成方面…...

GitHub 趋势日报 (2025年06月08日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...

WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)

一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解&#xff0c;适合用作学习或写简历项目背景说明。 &#x1f9e0; 一、概念简介&#xff1a;Solidity 合约开发 Solidity 是一种专门为 以太坊&#xff08;Ethereum&#xff09;平台编写智能合约的高级编…...

Spring AI 入门:Java 开发者的生成式 AI 实践之路

一、Spring AI 简介 在人工智能技术快速迭代的今天&#xff0c;Spring AI 作为 Spring 生态系统的新生力量&#xff0c;正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务&#xff08;如 OpenAI、Anthropic&#xff09;的无缝对接&…...

12.找到字符串中所有字母异位词

&#x1f9e0; 题目解析 题目描述&#xff1a; 给定两个字符串 s 和 p&#xff0c;找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义&#xff1a; 若两个字符串包含的字符种类和出现次数完全相同&#xff0c;顺序无所谓&#xff0c;则互为…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)

在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...