Android Display Graphics #1 整体框架介绍一

  1. 软件基础

Android的framework层提供了一系列的图像渲染API,可绘制2D和3D。简单理解就是上层开发APP的小伙伴提供了接口,开发者可以直接显示对应的自己内容。但如果掌握了Display底层逻辑再写上层app,会有掌控力,出问题可以根据log定位。

比如app用调用了

public class MainActivity extends AppCompatActivity {

或者

public class MainActivity extends Activity {

创建一个APP类型窗口,或者通过主动调用WindowManager.addView的方式来创建非App类型的窗口,都会调到ViewRootImpl。ViewRootImpl中有两个关键对象 mSurface和mSurfaceControl。

frameworks/base/core/java/android/view/ViewRootImpl.java

652      public final Surface mSurface = new Surface();

653      private final SurfaceControl mSurfaceControl = new SurfaceControl();

通过jni调到native层SurfaceControl。创建一个SurfaceFlinger的client端,new SurfaceComposerClient。通过这个client创建buffer和surface。这个surface就给到了app端。用户可以在上面绘制要显示的内容。绘制完成后将Surface(即buffer)传递到SurfaceFlinger合成,再给到HardwareComposer送显,最终显示到显示屏上。

几个基础概念:

Canvas

翻译过来就是 “画布”,也可以理解为绘制规则。是Java层的一个类,提供了一系列API,使用这些API可以实现各种的产品经理要求的效果。Canvas包含bitmap、线条、圆形、矩形、文字等绘制方法,是绘制 2D 对象的最简便方法,并且和bitmap、Surface相关联。

可通过如下几种方法创建:

1、通过构造方法。

kotlin

val canvas = Canvas()

canvas.setBitmap(bitmap)

绘制完的内容保存到Canvas的同期bitmap中。

kotlin

val canvas = Canvas(bitmap)  效果同上

2、重写View.onDraw

override fun onDraw(canvas: Canvas?) {

super.onDraw(canvas)

}

这也是我们使用最多的方式,自定义View时通过重写onDraw方法来实现。Canvas绘制的内容是显示在自定义View中。

3、通过SurfaceView

kotlin

val surfaceView = SurfaceView(context)   //从surfaceView的surfaceHolder里锁定获取Canvas

val canvas = surfaceView.holder.lockCanvas()  //进行canvas操作

......

Canvas surfaceView.holder.unlockCanvasAndPost(canvas)   //Canvas操作结束后解锁并执行

Kotlin Example:

canvas?.drawColor(context.getColor(R.color.blue))

OpenGL ES

目前电脑和手机都离不开GPU,但每个大厂都有自己的GPU,高通的adreno,ARM的mali,英伟达,Apple的等,如果各厂商的驱动接口各不相同,上层用户开发显示就太难了。如果有一套接口将复杂的、 各种各样的 GPU 硬件包装起来,各个电脑公司编写自家的驱动,然后提供出来 一套统一的接口,供上层软件工程师调用。这样,世界就和平了。

没错,OpenGL就是这套标准接口。OpenGL ES 为嵌入式设备 GPU 驱动的标准接口,比如手机, OpenGL ES 全称:OpenGL for Embedded Systems。

那谁这么牛逼定义了这套标准呢?Khronos 组织,这个众多大公司联合组建而来,比如 Apple、 Intel、AMD、Google、ARM、Qualcomm、Nvidia 等。针对 GPU 又提出了另外一套更底层的接口 Vulkan,这是一套比 OpenGL 更底层的接口。手机屏上显示的内容,2D或3D ,如果是 3D 的,不管是 App 还是游戏,或者简单的图片界面,底层都是通过 GPU、 通过 OpenGL(ES)绘制出来的。

对于 2D 渲染,Canvas是更简单的选择。Android NDK 中提供 OpenGL ES。android.opengl 和 javax.microedition.khronos.opengles 软件包提供 OpenGL ES 功能。

跟OpenGL ES协作的还有EGL(Embedded Graphic Interface)和GLSL(OpenGL Shading Language)两个好伙伴,后面有需要再分析。

Surface

这里其实理解为”画布”更合适,但会和Canvas混淆,所以不翻译。Surface表示一个用于合成的内存块。在电脑上编辑一张图片,首先要加载到内存,操作内存数据,再保存到本地。这个Surface就相当于你向系统申请的那个内存(Android 中是SurfaceFlinger),手机分辨率是1920*1080,那你申请的Surface大小和范围只要在[0,0]-[1920,1080]之间就可以。

把Surface理解为一个buffer也可以,Native层的Surface定义在/frameworks/native/libs/gui/include/gui/Surface.h,可以看到很多操作buffer的接口。

显示的不同阶段对这块内存的叫法不同,在上层可以是Window、ANnativeWindow、Surface、SurfaceView、layer、buffer,这些本质上没啥区别,可以广泛意义上理解为用于显示内容的那块内存,只不过各个阶段的操作接口不同。

Vulkan

Vulkan 是一个适用于高性能 3D 图形的低开销、跨平台 API。前面不是已经有OpenGL ES了,怎么又出来一个Vulkan呢?因为OpenGL虽然迭代了25年以上,并不断满足行业需求,但是现在已经逐渐满足不了行业的需要。且Khronos Group的各大佬成员都同意需要新一代的跨平台GPU API,由此Vulkan诞生了。

Vulkan诞生之初就决定了它一定要有跨平台属性,目的就是成为行业内的统一标准。

GPU的可编程性越来越强,越来越多的平台开始支持加速图形,计算,视觉和深度学习。灵活性和可移植性变得很重要。

性能上,OpenGL也不能充分发挥现代CPU多核多线程的性能优势。

Vulkan-新一代GPU API的特性

·Explicit(明确、透明)

GPU driver做更少的事情,把更多的控制权交给开发者

·Streamlined(精简)

更快的性能,更低的开销,更少的延迟

·Portable(可移植)

Cloud, desktop, console, mobile and embedded

·Extensible (可扩展)

支持新功能的扩展,推动行业技术进步

Vulkan有哪些优势呢?

·显式的GPU控制

OpenGL驱动中,驱动会帮你做API验证,内存管理,线程管理等大部分工作。OpenGL驱动大包大揽什么事情都管,即使应用使用API出错,也会帮忙解决处理,保证应用正常运行。开发者使用起来非常简单。Vulkan则不然。Vulkan把API验证、内存管理、多线程管理等工作交由开发者负责。一旦API使用出错,应用就会出现crash。没人帮应用兜底,所有事情都交由应用打理。这种方式无疑增加了API使用的复杂度和困难度,但换来的是性能上巨大的提升。

·CPU多线程的效率提升

在OpenGL中,所有的渲染操作都放在一个线程,其他线程就算处于空闲状态,也只能围观。

Vulkan中引入了 Command Buffer 的概念,每个线程都可以往Command Buffer 提交渲染命令,给开发者提供了充分发挥CPU多核多线程的优势。在复杂场景下,性能的提升非常客观!

· 可移植性

Vulkan可以支持各种平台。

Vulkan和OpenGL性能对比

Khronos给出了一张各个图形API理论性能对比:

PowerVR做了一个视频做了Vulkan和OpenGL的性能对比:

为防止视频丢失,可以关注微信公众号AndroidAVWorld 回复:OpenglVSVulkan 获取。

如何决定是使用OpenGL还是Vulkan呢?如果你定位到确实是OpenGL导致的性能问题,而不是GPU瓶颈,可以考虑使用Vulkan。但你要准备好适应更大难度的代码复杂度,更多开发量。

Android 给的画图方式有3种,即Canvas、OpenGL ES、Vulkan。原文如下:

App developers draw images to the screen in three ways: with Canvas, OpenGL ES, or Vulkan.

  1. 硬件与显示流程 

      两大组成部分:  渲染(Render) + 合成 (SurfaceFlinger + HWC)

渲染(Render)也可以叫做绘制(drawFrame),这样理解起来更具体些。

渲染(Render):将Surface中的空GraphicBuffer交给CPU或GPU将数据绘制到Surface上。把绘图指令转化为二维像素数组的过程,就叫做“渲染”。CPU通过Skia库,GPU通过Canvas。

合成  (Compose): SurfaceFlinger将几块有数据的Buffer 叠合成一张Buffer,交个HWC送到panel显示。

图像渲染大致步骤:

渲染是通过GPU和CPU共同完成的,CPU主要工作:计算显示内容,比如视图的创建、布局计算、图片解码、文本绘制等。GPU主要工作:Rasterization (栅格化),渲染到帧缓冲区rasterization光栅化,将图转化为一个个栅格组成的图象,每一个元素也就是意味着帧缓冲区中的一个像素。如下图所示

光栅化是一种非常消耗资源的活动,GPU就是为了解决这个问题而在上个世纪90年代引入的单独的图像处理单元。CPU 负责把 UI 组件计算成 Polygons,Texture 纹理,然后交给 GPU 进行栅格化渲染。

硬件加速的本质就是使用GPU代替CPU完成Graphic Buffer绘制工作,以实现更好的性能。

GPU

GPU全称是GraphicProcessing Unit,中文是图形处理器,其最大的作用就是进行各种绘制计算机图形所需的运算,包括顶点设置、光影、像素操作等。也就是用来执行我们开发者调用的一个个的“绘图指令”。所以,GPU实际上是多组图形函数API的集合,这些函数由硬件驱动实现。

合成就是把每个图层的内容,计算重叠区域的像素后,最终按照Z轴的上下顺序把多个图层合并为一个图层。

举个栗子:

launcher桌面,它由“壁纸”、“顶部的状态栏”、“桌面的应用列表”以及“底部导航栏”4个图层组成。

Layer1:壁纸

Layer2:顶部状态栏,显示时间等

Layer3:桌面应用列表

Layer4:底部导航栏

上面的Layer1-Layer4图层,都由GPU渲染出来。但图层与图层之间发生重叠(比如状态栏、应用列表和导航栏这3个图层都是叠加在壁纸图层的上面),重叠部分的像素颜色就需要重新计算。

DPU

合成工作的本质是执行计算“脏区域”、格式转换、处理缩放等操作,这些任务可以调用GPU的接口来完成。“图层渲染”那一步GPU已经完成了3D处理,所以图层合成的过程中不需要3D操作。

那只需要为合成流程单独配置一块2D渲染引擎就可以了。目前Android设备中,基本都是DPU芯片负责这个任务。

DPU作为图形硬件的一部分,通常被封装在GPU模块当中,最主要的功能是将GPU渲染完成的图层输出到屏幕。兼任了合成功能以后,对于图层重叠的部分,DPU会自动计算出“脏区域”并更新像素颜色变化。

不过,DPU虽然可以执行合成工作,但它有合成数量的限制。

例如Arm Mali-DP550最多支持7层合成任务。

一幅图像的显示必须要经过渲染、合成、送显这三个阶段,才能展现给用户。GPU和DPU就是用于提供给应用程序渲染和合成能力的硬件设备,其中:

·GPU芯片负责执行图形显示流程中的“渲染”工作

·DPU芯片负责执行图形显示流程中的“合成”工作

HWC

上面说到GPU和DPU都可以做合成任务,厂商可以选择将合成工作放在DPU中,也可以选择在板子上加一块2D渲染芯片,将合成工作放在这块芯片中,或者直接使用GPU合成。这就需要一个规范把合成工作抽象成一个接口,由厂商自由选择合成方案。

Hardware Composer就是专门用来定义合成工作的抽象接口,它是Android Hardware Abstraction Layer(HAL)硬件抽象层的成员之一。在HWC中,厂商使用的是DPU还是其他的2D渲染芯片不重要,只需要实现HWC的接口即可。

那使用GPU和DPU合成有什么差异?合成策略怎么选择呢?

1、DPU合成比GPU高效,有由显示硬件原始设备制造商OEM完成;

2、hwc中的硬件供应商定制决策代码,大致流程为:

sf进程:有8个渲染好的图层过来了,改怎么合成这些图层呢?都给你行不?

hwc:老弟,我最多只能处理5个图层的合并工作,其余3个图层我标记为GPU合成了,你处理吧。

sf进程:调用GPU完成另外3个图层的合成工作,并将合并后的图层交给hwc。

3、当有一个layer是透明的,并且叠加到一起显示时,HWC的合成会低于OpenGL的合成效率。

4、超出HWC能力的图层会调用GPU合成,如果应用的图层太多会对性能产生影响。

具体layer的合成方式,可以通过dumpsys  SurfaceFlinger来查看。

HWC模块还负责送显以及发送VSync信号等。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【ai】chatgpt的plugin已经废弃

发现找不到按钮,原来是要申请: https://openai.com/index/chatgpt-plugins/ 发现申请已经跳转了,好像是废弃了? 不接受新插件了,但是openai的api 是可以继续用的。 https://openai.com/waitlist/plugins/We are no longer accepting new Plugins, builders can now create…

医疗小程序源码SpringBoot2.X + Vue + UniAPP全栈开发

源码说明: 看到好多坛友都在求SpringBoot2.X Vue UniAPP,全栈开发医疗小程序 – 带源码课件,我看了一下,要么链接过期,要么课件有压缩密码。 特意整理了一份分享给大家,个人认为还是比较全面的。 希望…

最后两天!百度云加速正式停服

百度云加速将于5月30日,正式关闭服务器,仅保留官网首页通知。 届时如网站还在百度云加速接入的,将无法正常访问! 如果您还有域名在百度云加速接入的请尽快做迁移安排,以免造成损失。 目前在主机吧购买的域名已经全部…

使用华为快传同步文件至电脑

使用华为快传同步文件至电脑,电脑端未发现设备解决办法 1、手机和电脑连同一网络 2、打开手机华为分享,打开电脑网络 3、网络中找到设备,输入账户密码进行连接(未找到设备往下继续看) 未找到设备解决办法&#xff1…

攒粒是什么?怎么用攒粒赚钱?

攒粒简介 攒粒的前身是91问问,隶属于上海道道永泉市场调查有限公司,是一家专业的全球在线调研服务公司,也是是国内排名前列的社区调查之一,10年在线调研,600万会员亲身体验,提供网络调查、市场调查、问卷调…

Go源码--sync库(1)

简介 这篇主要介绍 sync.Once、sync.WaitGroup和sync.Mutex sync.Once once 顾名思义 只执行一次 废话不说 我们看源码 英文介绍直接略过了 感兴趣的建议读一读 获益匪浅 其结构体如下 Once 是一个严格只执行一次的object type Once struct {// 建议看下源码的注解&#xf…

联想应用商店开发者常见问题FAQ

Phone/Pad应用常见问题 应用上传FAQ Q. 上传apk包时,提示“该包名已存在”如何处理? A:若应用包名出现冲突,请先核实该账号是否已存在该包名产品,若不在该账号下,请进行应用认领。 Q. 应用是否可以授权…

AI图书推荐:用ChatGPT和Python搭建AI应用来变现

《用ChatGPT和Python搭建AI应用来变现》(Building AI Applications with ChatGPT API)将ChatGPT API与Python结合使用,可以开启构建非凡AI应用的大门。通过利用这些API,你可以专注于应用逻辑和用户体验,而ChatGPT强大的…

爬虫技术升级:如何结合DrissionPage和Auth代理插件实现数据采集

背景/引言 在大数据时代,网络爬虫技术已经成为数据收集的重要手段之一。爬虫技术可以自动化地从互联网上收集数据,节省大量人力和时间成本。然而,当使用需要身份验证的代理服务器时,许多现有的爬虫框架并不直接支持代理认证。这就…

three.js能实现啥效果?看过来,这里都是它的菜(11)

Hi,这是three.js动画效果第十一期分享了。 在 Three.js 中创建光线流边动画可以通过使用 ShaderMaterial 和自定义的着色器程序来实现。下面是一个简单的示例代码,演示了如何在 Three.js 中创建光线流边动画: // 创建场景 var scene new T…

【Qt】事件

文章目录 1 :peach:事件介绍:peach:2 :peach:事件的处理:peach:3 :peach:按键事件:peach:3.1 :apple:单个按键:apple:3.2 :apple:组合按键:apple: 4 :peach:鼠标事件:peach:4.1 :apple:鼠标单击事件:apple:4.2 :apple:鼠标释放事件:apple:4.3 :apple:鼠标双击事件:apple:4.4 :a…

python下载安装教程(最新图文下载)__python下载

一、下载安装包 官网下载,下载流程参考下面截图。 下载安装python安装包,网盘点此下载::点击此处直接下载 点击图片中的“Download”按钮,然后选择需要下载的版本,最后在跳转的页面中,选择你…

VM中Ubuntu16.04的下载以及ROS—kinetic的版本下载

一、Ubuntu镜像地址 转载备份一下; 官方下载地址(不推荐) https://www.ubuntu.com/downloadhttps://www.ubuntu.com/download 中科大源 Index of /ubuntu-releases/16.04/http://mirrors.ustc.edu.cn/ubuntu-releases/16.04/ 阿里云开…

【Leetcode 160】环形链表——双指针,细节讲解

题目 给你一个链表的头节点 head ,判断链表中是否有环。 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置&#…

Web安全:文件上传漏洞详解,文件上传漏洞原理、绕过方式和防御方案。

「作者简介」:2022年北京冬奥会网络安全中国代表队,CSDN Top100,就职奇安信多年,以实战工作为基础对安全知识体系进行总结与归纳,著作适用于快速入门的 《网络安全自学教程》,内容涵盖系统安全、信息收集等…

在XP/Vista系统下使用Node.js的babel-cli命令行工具转码ES6语法的js文件,让IE8浏览器也能运行

在XP系统下IE浏览器最高只能装到IE8,在Vista系统下最高只能装到IE9。 2015年以后,JavaScript新增了很多语法,比如class、extends,还有let和const等等,这些语法都是XP下的终端浏览器IE8所不支持的。要想让使用了这些新式…

【Django】中间件实现钩子函数预处理和后处理,局部装饰视图函数

在app文件夹里新建middleware.py继承MiddlewareMixin, 编写中间件类,重写process_request、process_response钩子函数 from django.http import HttpRequest, HttpResponse from django.utils.decorators import decorator_from_middleware from django…

NAT 网络转换

NAT(Network Address Translation) 网络地址转换 0x01 NAT 简介 为什么要使用 NAT IPv4 网络地址紧缺,从而出现了私有网段,来补充地址,但私有网段不课访问 internet 所以出现了 NAT 地址转换,将私有地址,转换为公网 I…

typora自动生成标题序号(修改V1.0)

目录 带序号效果图 解决方法 带序号效果图 解决方法 1.进入文件夹:文件–>偏好设置–>外观–>主题–>打开主题文件夹 2.如果没有base.user.css文件,新建一个。如果有直接用记事本打开,把下面代码拷贝进去保存。 /** initiali…

rfid资产管理系统如何帮助医院管理耗材的

RFID资产管理系统可以帮助医院管理耗材,提高耗材管理的效率和准确性。以下是它可以发挥作用的几个方面: 1. 实时跟踪和定位:使用RFID标签附加在耗材上,可以实时跟踪和定位耗材的位置。医院可以通过系统查询耗材的实时位置&#xf…