https://source.android.com/devices/graphics
综述:
应用开发者可通过三种方式将图像绘制到屏幕上:使用画布、OpenGL ES 或 Vulkan。无论开发者使用什么渲染 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 是合成器,而硬件混合渲染器是制作器。
BufferQueueBufferQueues 是 Android 图形组件之间的粘合剂。它们是一对队列,可以调解缓冲区从生产方到消耗方的固定周期。一旦生产方移交其缓冲区,SurfaceFlinger 便会负责将所有内容合成到显示部分。
有关 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 图形渲染的中心点。
BufferQueuehttps://source.android.com/devices/graphics/arch-bq-gralloc
BufferQueue 类将可生成图形数据缓冲区的组件(生产方)连接到接受数据以便进行显示或进一步处理的组件(使用方)。几乎所有在系统中移动图形数据缓冲区的内容都依赖于 BufferQueue。
Surface
https://source.android.com/devices/graphics/arch-sh
Surface 是一个接口,供生产方与消耗方交换缓冲区。
用于显示 Surface 的 BufferQueue 通常配置为三重缓冲。缓冲区是按需分配的,因此,如果生产方足够缓慢地生成缓冲区(例如在 60 fps 的显示屏上以 30 fps 的速度进行缓冲),队列中可能只有两个分配的缓冲区。按需分配缓冲区有助于最大限度地减少内存消耗。您可以在 dumpsys SurfaceFlinger
的输出中看到每个层级关联的缓冲区的摘要。
大多数客户端使用 OpenGL ES 或 Vulkan 渲染到 Surface 上。但是,有些客户端使用画布渲染到 Surface 上。
画布实现由 Skia 图形库提供。如果您要绘制一个矩形,可以调用 Canvas API,它会在缓冲区中适当地设置字节。
SurfaceFlinger
https://source.android.com/devices/graphics/surfaceflinger-windowmanager
SurfaceFlinger 可通过两种方式接受缓冲区:通过 BufferQueue 和 SurfaceControl,或通过 ASurfaceControl。
SurfaceFlinger 接受缓冲区的一种方式是通过 BufferQueue 和 SurfaceControl。当应用进入前台时,它会从 WindowManager 请求缓冲区。然后,WindowManager 会从 SurfaceFlinger 请求层。层是 surface(包含 BufferQueue)和 SurfaceControl(包含显示框架等层元数据)的组合。SurfaceFlinger 创建层并将其发送至 WindowManager。然后,WindowManager 将 Surface 发送至应用,但会保留 SurfaceControl 来操控应用在屏幕上的外观。
SurfaceFlinger 接受缓冲区,对它们进行合成,然后发送到屏幕。WindowManager 为 SurfaceFlinger 提供缓冲区和窗口元数据,而 SurfaceFlinger 可使用这些信息将 Surface 合成到屏幕。
WindowManager
https://source.android.com/devices/graphics/surfaceflinger-windowmanager
WindowManager 会控制窗口对象,它们是用于容纳视图对象的容器。窗口对象始终由 Surface 对象提供支持。WindowManager 会监督生命周期、输入和聚焦事件、屏幕方向、转换、动画、位置、变形、Z 轴顺序以及窗口的许多其他方面。WindowManager 会将所有窗口元数据发送到 SurfaceFlinger,以便 SurfaceFlinger 可以使用这些数据在屏幕上合成 Surface。
SurfaceFlinger和WindowManager关系
SurfaceFlinger 接受缓冲区,对它们进行合成,然后发送到屏幕。WindowManager 为 SurfaceFlinger 提供缓冲区和窗口元数据,而 SurfaceFlinger 可使用这些信息将 Surface 合成到屏幕。
硬件混合渲染器 HAL
https://source.android.com/devices/graphics/hwc
硬件混合渲染器 (HWC) HAL 用于确定通过可用硬件来合成缓冲区的最有效方法。作为 HAL,其实现是特定于设备的,而且通常由显示硬件原始设备制造商 (OEM) 完成。
HWC 会执行以下计算:
- SurfaceFlinger 向 HWC 提供一个完整的层列表,并询问“您希望如何处理这些层?”
- HWC 的响应方式是将每个层标记为设备或客户端合成。
- SurfaceFlinger 会处理所有客户端,将输出缓冲区传送到 HWC,并让 HWC 处理其余部分。
Android 设备通常支持 4 个叠加平面。尝试合成的层数多于叠加层数会导致系统对其中一些层使用 GLES 合成,这意味着应用使用的层数会对能耗和性能产生重大影响。
Android图形系统综述(干货篇)
https://juejin.cn/post/6898525503960186887
开发者可通过三种方式将图像绘制到屏幕上:Canvas, OpenGL ES 或 Vulkan。无论使用什么渲染API,一切内容都会渲染到Surface,Surface 表示 BufferQueue 中的生产方,而 BufferQueue 通常被 SurfaceFlinger 消费。在 Android 平台上创建的每个 Window 都由 Surface 提供支持,所有被渲染的可见 Surface 都被 SurfaceFlinger 合成到显示部分。
- View: 视图,绘制到屏幕上的内容,如 TextView, ImageView 等。
- Window: View 的载体,对 Window 进行添加和删除需要通过 WindowManager 来操作。Window 并不是真实存在的,View 才是 Android 中的视图呈现形式,View 不能单独存在,它必须依附在 Window 这个抽象的概念上面。
- WindowManager: 管理系统中的 Window, 实际功能通过 Binder IPC 借由 WindowManagerService 实现。
- Canvas: 提供一些对 Surface 绘图的 API 用来进行实际的绘图操作。如果是软件绘制,其 drawXXX 方法会将内容绘制到 Bitmap 上;如果是硬件绘制,其 drawXXX 方法会抽象成 DrawOp 操作,然后添加到 DisplayList 中被 GPU 渲染。
- Surface: 一个 Window 对应一个 Surface(当存在 SurfaceView 则例外,Java Surface 实例存在于 ViewRootImpl 中,对应 native 层的 Surface 对象)。Surface 内部持有一个 BufferQueueProducer 指针(在 Layer 中创建)可以生产图像缓存区用来绘图,与 App 和 SurfaceFlinger 形成一个生产者消费者模型。
- Layer: App 请求创建 Surface 时 SurfaceFlinger 会创建 Layer 对象,它是 SurfaceFlinger 合成的基本操作单元,因此一个 Surface 对应一个 Layer。它创建有一个 BufferQueueProducer 生产者和 BufferQueueConsumer 消费者,这两个对象与像素数据的存储与转移相关。用户最终看到的屏幕内容是许多 Layer 按照 z-order 混合的结果。
- SurfaceView: 一种较之 TextView, Button 等更为特殊的 View, 它不与其宿主的 Window 共享一个 Surface, 而是有自己的独立 Surface。并且它可以在一个独立的线程中绘制 UI。因此 SurfaceView 一般用来实现比较复杂的图像或动画/视频的显示。
- Choreographer: 编舞者,用来控制当收到 VSync 信号后才开始绘制任务,保证绘制拥有完整的16.6ms。通常应用层不会直接使用Choreographer,而是使用更高级的API,如View.invalidate()等,可以通过Choreographer来监控应用的帧率。
- SurfaceFlinger: 管理消费当前可见的 Surface,所有被渲染的可见 Surface 都被 SurfaceFlinger,通过 WindowManager 提供的信息合成(使用 OpenGL 和 HardWare Composer,合成的数据源是上面提及的 BufferQueue 中的 GraphicBuffer)提交到屏幕的后缓冲区,等待屏幕的下一个Vsync信号到来,再显示到屏幕上。SufaceFlinger 通过屏幕后缓冲区与屏幕建立联系,同时通过 Surface 与上层建立联系,起到了一个承上启下的作用。
- HWComposer: HardWare Composer, 定义一套 HAL 层接口,芯片厂商根据硬件特点来实现这套接口。其主要工作是将 SurfaceFlinger 计算后的 Layer 显示参数合成到显示器 Buffer 上。当然 SurfaceFlinger 并非是 HWC 的唯一输入源,例如摄像头的预览输入 Buffer 可以由硬件设备直接写入,然后作为 HWC 的输入之一与 SurfaceFlinger 的输出做最后的合成。
- OpenGL: 一个 2D/3D 的图形库,需要底层硬件(GPU)和驱动来支持。移动端通常使用其子集 OpenGl ES(OpenGl for Embedded System)。
- Display: 显示设备的抽象,传统的 Display 设备是手机屏,此外 Android 也支持其他的外部输入设备如 HDMI, Wifi Display 等,将 SurfaceFlinger, OpenGL, HWComposer 合成后的数据输出到 Display 设备的缓存区用来显示。