图形

Android 图形 HAL 图标

Android 框架提供了各种用于 2D 和 3D 图形渲染的 API,可与制造商的图形驱动程序实现代码交互,因此务必更好地了解这些 API 的工作原理。这类驱动程序的构建基于图形硬件抽象层 (HAL),本页介绍了相关图形 HAL。在继续学习本部分之前,请先熟悉以下术语:

画布(通用术语)、Canvas(API 元素)
画布是一种绘图 Surface,用于对照位图或 Surface 对象来处理实际位合成。Canvas 包含关于位图、线条、圆形、矩形、文字等的标准计算机绘制方法,并与位图或 Surface 相关联。画布是在屏幕上绘制 2D 对象的最简便方法。基类为 Canvas
可绘制对象
可绘制对象是一种经过编译的视觉资源,可用作背景、标题或界面的其他部分。可绘制对象通常会被加载到另一个界面元素中,例如作为背景图片。可绘制对象不能接收事件,但可以指定各种其他属性(如状态和调度),以启用动画对象或图像库等子类。许多可绘制对象都是加载自可绘制资源文件(即描述图像的 XML 或位图文件)。可绘制资源会被编译成 android.graphics.drawable 的子类。如需详细了解可绘制对象和其他资源,请参阅资源
布局资源
布局资源是描述 activity 界面布局的 XML 文件。如需了解详情,请参阅布局资源
九宫格(9 宫格、NinePatch)
九宫格是一种可调整大小的位图资源,可用作设备上的背景或其他图片。如需了解详情,请参阅九宫格
OpenGL ES
OpenGL ES 是一个用于渲染 2D 和 3D 图形的跨平台 API。Android 提供 OpenGL ES 库,该库可用于实现硬件加速的 3D 渲染。对于 2D 渲染,画布是更简单的选项。Android 原生开发套件 (NDK) 中提供 OpenGL ES。android.opengljavax.microedition.khronos.opengles 软件包提供 OpenGL ES 功能。
Surface (通用术语)、Surface(API 元素)
Surface 表示要合成到界面的内存块。Surface 包含用于绘图的 Surface 对象,并提供各种辅助方法来绘制图层和调整界面大小。请使用 SurfaceView 类,而不是直接使用 Surface 类。
Surface 视图(通用术语)、SurfaceView(API 元素)
Surface 视图是一个 View 对象,它封装用于绘制的 Surface 对象,并提供相应的方法来动态指定其大小和格式。Surface 视图针对资源密集型操作(例如游戏或相机预览)提供了一种独立于界面线程进行绘制的方式,但也会因此占用额外的内存。Surface 视图同时支持画布和 OpenGL ES 图形。SurfaceView 对象的基类是 SurfaceView
主题
主题用于定义各种默认显示设置,它是一组捆绑在一起的属性,例如文字大小和背景颜色。Android 提供了一些标准的主题,这些主题列于 R.style 中,并以 Theme_ 开头。
视图(通用术语)、View(API 元素)
视图会在屏幕上绘制为矩形区域并用于处理点击、按键和其他互动事件。View 类是 activity 或对话框界面的大多数布局组件(如文本框和窗口)的基类。View 对象接收来自其父对象(请参阅 ViewGroup)的调用,以绘制自身,并告知父对象其首选大小和位置,但父对象不一定会遵循。如需了解详情,请参阅 View
视图组(通用术语)、ViewGroup(API 元素)
视图组用于对一组子视图进行分组。视图组负责确定子视图的位置和大小,以及在适当的时候调用每个子视图来绘制自身。某些视图组是不可见的,仅用于布局,而有些视图组则具有固有的界面(例如,滚动列表框)。视图组位于 widget 软件包中,但会扩展 ViewGroup 类。
视图层次结构
视图层次结构是视图和视图组对象的排列方式,定义应用中每个组件的界面。层次结构由视图组构成,而视图组中又可包含一个或多个子视图或视图组。在进行调试和优化时,您可以通过 Android SDK 提供的 Hierarchy Viewer 获得视图层次结构的可视化表示。
Vulkan
Vulkan 是一个适用于高性能 3D 图形的低开销、跨平台 API。
widget
widget 是一组完全实现的视图子类,这些子类用于渲染表单元素和其他界面组件,例如文本框或弹出式菜单。由于微件是完全实现的,因此它会自行处理测量和绘制,并且会响应屏幕事件。widget 位于 android.widget 软件包中。
窗口(通用术语)、Window(API 元素)
在 Android 应用中,窗口是派生自 Window 抽象类的对象,可指定常规窗口的元素,例如外观和风格、标题栏文字、菜单的位置和内容。对话框和 activity 使用 Window 类的实现来渲染 Window 对象。您无需在应用中实现 Window 类或使用窗口。

应用开发者可通过三种方式将图像绘制到屏幕上:使用画布OpenGL ESVulkan

Android 图形组件

无论开发者使用什么渲染 API,一切内容都会渲染到 surface 上。Surface 表示缓冲区队列中的生产方,而缓冲区队列通常会被 SurfaceFlinger 消耗。在 Android 平台上创建的每个窗口都由 Surface 提供支持。所有被渲染的可见 Surface 都被 SurfaceFlinger 合成到屏幕。

下图显示了关键组件如何协同工作:

图像渲染组件

图 1. surface 如何被渲染

主要组件如下所述:

图像流生产方

图像流生产方可以是生成图形缓冲区以供消耗的任何内容。例如 OpenGL ES、Canvas 2D 和 mediaserver 视频解码器。

图像流消耗方

图像流的最常见消耗方是 SurfaceFlinger,该系统服务会消耗当前可见的 Surface,并使用窗口管理器中提供的信息将它们合成到屏幕。SurfaceFlinger 是可以修改所显示部分内容的唯一服务。SurfaceFlinger 使用 OpenGL 和 Hardware Composer 来合成一组 Surface。

其他 OpenGL ES 应用也可以消耗图像流,例如相机应用会消耗相机预览图像流。非 GL 应用也可以是使用方,例如 ImageReader 类。

硬件混合渲染器

显示子系统的硬件抽象实现。SurfaceFlinger 可以将某些合成工作委托给硬件混合渲染器,以分担 OpenGL 和 GPU 上的工作量。SurfaceFlinger 只是充当另一个 OpenGL ES 客户端。因此,在 SurfaceFlinger 将一个或两个缓冲区合成到第三个缓冲区中的过程中,它会使用 OpenGL ES。这会让合成的功耗比通过 GPU 执行所有计算时更低。

硬件混合渲染器 HAL 则进行另一半的工作,是所有 Android 图形渲染的中心点。Hardware Composer 必须支持事件,其中之一是 VSYNC(另一个是支持即插即用 HDMI 的热插拔)。

Gralloc

需要使用图形内存分配器 (Gralloc) 来分配图像生产方请求的内存。有关详情,请参阅 Gralloc HAL

数据流

有关 Android 图形管道的描述,请参见下图:

图形数据流

图 2. 流经 Android 的图形数据流

左侧的对象是生成图形缓冲区的渲染器,如主屏幕、状态栏和系统界面。SurfaceFlinger 是合成器,而硬件混合渲染器是混合渲染器。

BufferQueue

BufferQueues 是 Android 图形组件之间的粘合剂。它们是一对队列,可以调解缓冲区从生产方到消耗方的固定周期。一旦生产方移交其缓冲区,SurfaceFlinger 便会负责将所有内容合成到显示部分。

有关 BufferQueue 通信过程,请参见下图。

BufferQueue 通信过程

图 3. BufferQueue 通信过程

BufferQueue 包含将图像流生产方与图像流消耗方结合在一起的逻辑。图像生产方的一些示例包括由相机 HAL 或 OpenGL ES 游戏生成的相机预览。图像消耗方的一些示例包括 SurfaceFlinger 或显示 OpenGL ES 流的另一个应用,如显示相机取景器的相机应用。

BufferQueue 是将缓冲区池与队列相结合的数据结构,它使用 Binder IPC 在进程之间传递缓冲区。生产方接口,或者您传递给想要生成图形缓冲区的某个人的内容,即是 IGraphicBufferProducer(SurfaceTexture 的一部分)。BufferQueue 通常用于渲染到 Surface,并且与 GL 消耗方及其他任务一起消耗内容。

BufferQueue 可以在三种不同的模式下运行:

类同步模式 - 默认情况下,BufferQueue 在类同步模式下运行,在该模式下,从生产方进入的每个缓冲区都在消耗方那退出。在此模式下不会舍弃任何缓冲区。如果生产方速度太快,创建缓冲区的速度比消耗缓冲区的速度更快,它将阻塞并等待可用的缓冲区。

非阻塞模式 - BufferQueue 还可以在非阻塞模式下运行,在此类情况下,它会生成错误,而不是等待缓冲区。在此模式下也不会舍弃缓冲区。这有助于避免可能不了解图形框架的复杂依赖项的应用软件出现潜在死锁现象。

舍弃模式 - 最后,BufferQueue 可以配置为丢弃旧缓冲区,而不是生成错误或进行等待。例如,如果对纹理视图执行 GL 渲染并尽快绘制,则必须丢弃缓冲区。

为了执行这项工作的大部分环节,SurfaceFlinger 就像另一个 OpenGL ES 客户端一样工作。例如,当 SurfaceFlinger 正在积极地将一个缓冲区或两个缓冲区合成到第三个缓冲区中时,它使用的是 OpenGL ES。

Hardware Composer HAL 执行另一半工作。该 HAL 充当所有 Android 图形渲染的中心点。