Android图形系统是系统框架中一个非常重要的子系统,与其它子系统一样,Android 框架提供了各种用于 2D 和 3D 图形渲染的 API供开发者使用来创建绚丽多彩的应用APP。图形渲染的 API的底层可与制造商的图形驱动程序实现代码交互,了解这些API的工作原理及图形系统框架层的处理逻辑可以帮助我们更好的使用这些功能。
本系列文章将侧重于图形系统BufferQueue的知识做分析讲解。BufferQueues 是 Android 图形组件之间的粘合剂,BufferQueue 类将生成图形数据缓冲区的组件(producers)连接到接受数据以便进行显示或进一步处理的组件(consumers)。几乎所有在系统中移动图形数据缓冲区的内容都依赖于 BufferQueue。理解BufferQueue的工作逻辑及图形缓冲区移动流程对于我们学习Android图形系统工作机制非常重要。
本篇作为该系列的开篇,我们将从Android图形系统的一些基本概念入手。
接下来就开始我们的学习之旅。
注:本系列文章的分析及代码均基于Android 12(S) Source Code,可参考:http://aospxref.com/ 或 http://aosp.opersys.com/
2 Android图形系统基本概述 2.1 Android 图形组件Android图形系统涉及到非常多的组件,比如 Surface、SurfaceHolder、EGLSurface、SurfaceView、GLSurfaceView、SurfaceTexture、TextureView、SurfaceFlinger等,比如下图展示的:
低级别组件
BufferQueue 和 gralloc。BufferQueue 将可生成图形数据缓冲区的组件(生产者)连接到接受数据以便进行显示或进一步处理的组件(消费者)。通过供应商专用 HAL 接口实现的 gralloc 内存分配器将用于执行缓冲区分配任务。SurfaceFlinger、Hardware Composer 和虚拟显示屏。SurfaceFlinger 接受来自多个源的数据缓冲区,然后将它们进行合成并发送到显示屏。Hardware Composer HAL (HWC) 确定使用可用硬件合成缓冲区的最有效的方法,虚拟显示屏使合成输出可在系统内使用(录制屏幕或通过网络发送屏幕)。Surface、Canvas 和 SurfaceHolder。Surface 可生成一个通常由 SurfaceFlinger 使用的缓冲区队列。当渲染到 Surface 上时,结果最终将出现在传送给消费者的缓冲区中。Canvas API 提供一种软件实现方法(支持硬件加速),用于直接在 Surface 上绘图(OpenGL ES 的低级别替代方案)。与视图有关的任何内容均涉及到 SurfaceHolder,其 API 可用于获取和设置 Surface 参数(如大小和格式)EGLSurface 和 OpenGL ES。OpenGL ES (GLES) 定义了旨在与 EGL 结合使用的图形渲染 API。EGI 是一个通过操作系统创建和访问窗口的库(要绘制纹理多边形,请使用 GLES 调用;要将渲染应用到屏幕上,请使用 EGL 调用)。此页还介绍了 ANativeWindow,它是 Java Surface 类的 C/C++ 等价类,用于通过原生代码创建 EGL 窗口表面。Vulkan。Vulkan 是一种用于高性能 3D 图形的低开销、跨平台 API。与 OpenGL ES 一样,Vulkan 提供用于在应用中创建高质量实时图形的工具。Vulkan 的优势包括降低 CPU 开销以及支持 SPIR-V 二进制中间语言。高级别组件
SurfaceView 和 GLSurfaceView。SurfaceView 结合了 Surface 和 View。SurfaceView 的 View 组件由 SurfaceFlinger(而不是应用)合成,从而可以通过单独的线程/进程渲染,并与应用界面渲染隔离。GLSurfaceView 提供了用于管理 EGL 上下文、线程间通信以及与 Activity 生命周期的交互的辅助程序类(但不是必须使用 GLES)。SurfaceTexture。 SurfaceTexture 将 Surface 和 GLES 纹理相结合来创建 BufferQueue,而您的应用是 BufferQueue 的消费者。当生产者将新的缓冲区排入队列时,它会通知您的应用。您的应用会依次释放先前占用的缓冲区,从队列中获取新缓冲区并执行 EGL 调用,从而使 GLES 可将此缓冲区作为外部纹理使用。Android 7.0 添加了对安全纹理视频播放的支持,以便对受保护的视频内容进行 GPU 后处理。TextureView。 TextureView 结合了 View 和 SurfaceTexture。TextureView 对 SurfaceTexture 进行包装,并负责响应回调以及获取新的缓冲区。在绘图时,TextureView 使用最近收到的缓冲区的内容作为其数据源,根据 View 状态指示,在它应该渲染的任何位置和以它应该采用的任何渲染方式进行渲染。View 合成始终通过 GLES 来执行,这意味着内容更新可能会导致其他 View 元素重绘。Android图形组件相互配合、沟通,共同组成一个完善的图形显示子系统,同时在Java level与Native level面向开发者提供了可编程的接口。
2.2 Android 图形组件协同工作无论开发者使用什么渲染 API,一切内容都会渲染到 Surface 上。Surface 表示缓冲区队列中的生产者,而缓冲区队列通常会被 SurfaceFlinger 消耗。在 Android 平台上创建的每个窗口都由 Surface 提供支持。所有被渲染的可见 Surface 都被 SurfaceFlinger 合成到屏幕。
下图显示了关键组件如何协同工作:
对于Android 12 后的系统,我自己理解下图来表示各个组件间的协同工作:
或者如下这个图:
从工作流程的角度去看,主要组件如下所述:
图像流生产者(Image Stream Producers)图像流生产者可以是生成图形缓冲区以供消耗的任何内容。例如 OpenGL ES、Canvas 2D 和 mediaserver 视频解码器。
图像流消费者(Image stream consumers)图像流的最常见消费者是 SurfaceFlinger,该系统服务会消耗当前可见的 Surface,并使用窗口管理器中提供的信息将它们合成到屏幕。SurfaceFlinger 是可以修改所显示部分内容的唯一服务。SurfaceFlinger 使用 OpenGL 和 Hardware Composer 来合成一组 Surface。
其他 OpenGL ES 应用也可以消耗图像流,例如相机应用会消耗相机预览图像流。非 GL 应用也可以是使用方,例如 ImageReader 类。
硬件混合渲染器(Hardware Composer)显示子系统的硬件抽象实现。SurfaceFlinger 可以将某些合成工作委托给硬件混合渲染器(HWC),以分担 OpenGL 和 GPU 上的工作量。SurfaceFlinger 只是充当另一个 OpenGL ES 客户端。因此,在 SurfaceFlinger 将一个或两个缓冲区合成到第三个缓冲区中的过程中,它会使用 OpenGL ES。这会让合成的功耗比通过 GPU 执行所有计算时更低。
硬件混合渲染器 HAL 则进行另一半的工作,是所有 Android 图形渲染的中心点。Hardware Composer 必须支持事件,其中之一是 VSYNC(另一个是支持即插即用 HDMI 的热插拔)。
GrallocGralloc可以理解为图形内存分配器,用来分配和管理图像生产者请求的内存(即图形数据缓冲区Graphic Buffers)
二的次方
2.3 数据流有关 Android graphics pipeline的描述,请参见下图:
左侧的对象是生成图形缓冲区的渲染器,如主屏幕、状态栏和系统界面。SurfaceFlinger 是合成器,接受多个来源的图形显示数据,将他们合成,然后发送到显示设备。硬件混合渲染器HWC是制作器。SurfaceFlinger与HWC配合用来将 Surface 合成到屏幕BufferQueue
BufferQueues 是 Android 图形组件之间的粘合剂。它们是一对图像缓冲区队列,可以调解缓冲区从生产者到消费者的固定周期。一旦生产者移交其缓冲区,SurfaceFlinger 便会负责将所有内容合成到显示部分。
有关 BufferQueue 通信过程,请参见下图。
BufferQueue 包含将图像流生产者与图像流消费者结合在一起的逻辑。BufferQueue 类是 Android 中所有图形处理操作的核心。它的作用很简单:将生成图形数据缓冲区的一方(生产方)连接到接受数据以进行显示或进一步处理的一方(消耗方)。几乎所有在系统中移动图形数据缓冲区的内容都依赖于 BufferQueue。
通过上图我们可以大概看到BufferQueue的工作过程:
图像生产者通过调用dequeue方法向BufferQueue请求一块图形缓冲区内存,即一块GraphicBuffer;图像生产者将产生的图像数据(比如相机预览的图像或解码器解码出的视频帧)写入图形缓冲区GraphicBuffer,并通过queue方法提交给BufferQueue;BufferQueue收到图形缓冲区GraphicBuffer的入队列消息,通知图像消费者调用acquire方法取得已填充数据的buffer进行处理或显示;图像消费者处理完毕,调用release方法把buffer归还给BufferQueue,这个buffer之后可再重复使用;图像生产者、BufferQueue、图像消费者协调工作,图形缓冲区buffer在三者之间协调流转,图像便流畅的显示或处理。 3 小结通过上面的一些介绍,我们对Android图形系统的一些基本组成及概念有了一个大概的了解。为了更深刻的理解这些抽象的内容,下一篇文章我们将从Native Level入手,基于Android图形系统API写作一个简单的图形处理小程序。
必读:Android 12(S) 图像显示系统 - 开篇
参考
https://www.jianshu.com/p/824a9ddf68b9
https://www.cnblogs.com/1996swg/p/9790209.html
https://source.android.com/devices/graphics
https://www.pianshen.com/article/98181094083/