写点什么

Android 图形渲染系统新

作者:江湖修行
  • 2023-03-15
    北京
  • 本文字数:3257 字

    阅读完需:约 11 分钟

Android图形渲染系统新

Android 图形渲染系统是 Android 不可或缺的子系统之一,其本身复杂且与其他子系统存在千丝万缕的联系,各种模块众多,内容繁杂,各个版本都会有一定的更新,很难一篇文章道完天机,后续希望能出个系列文章好好讲解内中玄机,本文作为系列的开篇,希望能系统的讲解下各模块的机制,虽然之前也写过相关文章,但是本篇文章带来了不一样的内容。

众所周知手机已是人们生活中不可或缺的一部分,手机也天然的成为了移动端的一个最重要的流量底座,承载着用户各种精神和物质上的需求,其中交互体验和感受又是用户最直接的反应,而渲染系统是保障这一切的根基。

首先我们以官方的一张图作为切入点



该图展示了图形系统的关键组件协作流程和图形数据的流转:

  • OpenGL ES、MediaPlayer、Camera 等生产者生产 GraphicBuffer 到 Surface

  • Surface 通过 IGraphicBufferProducer 把 GraphicBuffer 跨进程传输给消费者 SurfaceFlinger

  • SurfaceFlinger 根据 WMS 提供的窗口信息合成所有的 Layer,具体的合成策略由 hwcomposerHAL 模块决定并实施,

  • 最后也是由该模块送到 Display 模块,而 Gralloc 模块则负责分配图形缓冲区。 

但上图是 16 年官方给出的,随着几年的更新也引入了一些新的模块,支持了新的图形库-Vulkan,Gralloc 和 BufferQueue 也做了相应的支持,我们可以继续细化下整体流程,全景图如下:



从上图可看出整个渲染系统贯穿 app 和系统层,app 在 CPU 侧进行图形数据的生产,然后交给 GPU 做渲染处理,最后由 SurfaceFlinger 和 HWC 配合进行合成并渲染上屏,其间涉及了多个核心模块的协作,下面我们进行重点的讲解: 

 Graphic Buffer Producers

产生 graphic buffers 的生产者. 例如 OpenGL ES, Vulkan, Media 的视频解码器,Camera 等.

Graphic Buffer Consumers

最核心的消费者便是 SurfaceFlinger,它使用 OpenGL 和 Hardware Composer 来组合一组 surfaces

  • OpenGL ES 应用能消费图形流, 比如 camera app 消费 camera 预览图形流;

  • 非 OpenGL ES 应用也能消费, 比如 ImageReader 类

Canvas

Canvas 是一个 2D 图形 API ,是 Android View 树实际的渲染者。Canvas 又可分为 Skia 软件绘制和 hwui 硬件加速绘制。

Window Manager

用于管理 Window.Window 是个抽象类,表示一个窗口,其实现是 PhoneWIndow。WindowManager 会监督生命周期、输入和聚焦事件、屏幕方向、转换、动画、位置、变形、Z 轴顺序以及窗口的许多其他方面。当 app 通过 WindowManager 创建一个 Window 时,WindowManagerService 会为每一个 Window 创建一个 Surface,并将各种(包括屏幕信息,z-order 等)信息发送给 SurfaceFlinger。

Surface

Surface 表示 APP 进程的一个窗口,承载了窗口的图形数据与 SurfaceFlinger 侧的 Layer 相对应 。从 App 侧来看不管是 Canvas , OpenGL ES 还是 Vulkan 最终渲染到的目标都是 Surface ,现在比较流行的跨平台 UI 框架 Flutter 在 Android 平台上也是直接渲染到 Surface 。

一个 Activity 是一个 Surface、一个 Dialog 也是一个 Surface。

BufferQueue



安卓图形渲染设计有一个生成者消费者模式,BufferQueue 即是这种模式的写照。Android 图形系统包含了两对生产者和消费者模型,它们都通过 BufferQueue 进行连接:

  • Canvas ,OpenGL ES 和 Vulkan 生产图形数据,SurfaceFlinger 消费图形数据。

  • SurfaceFlinger 合成所有图层的图形数据,Display 显示合成结果。

BufferQueue 是连接 Surface 和 Layer 的纽带,当上层图形数据渲染到 Surface 时,实际是渲染到了 BufferQueue 中的一个 GraphicBuffer,然后通过 IGraphicBufferProducer 把 GraphicBuffer 提交到 BufferQueue ,让 SurfaceFlinger 进行后续的合成显示工作。GraphicBuffer 代表的图形缓冲区是由 Gralloc 模块分配的,并且可以跨进程传输(实际传输的只是一个指针),为了高效传输大块数据,使用匿名共享内存。

BufferQueue 的经典工作流程如下:

  • 生产者请求一块空闲的缓存区:dequeueBuffer()

  • 生产者填充缓存区并返回给队列: queueBuffer()

  • 消费者获取一块缓存区: acquireBuffer()

  • 消费者使用完毕,则返回给队列: releaseBuffer()

SurfaceFlinger

Android 系统服务,会随着 init 进程执行 init.rc 而创建该服务。负责合成所有 Surface 提供的图形数据,然后送显到屏幕。SurfaceFlinger 既是上层应用的消费者,又是 Display 的生产者。功能如下:

  • 分配图形缓冲区

  • 合成 Surface

  • 管理 VSYNC 事件


SurfaceFlinger 就是将多个 Surface 里的内容进行合成,最后提交到屏幕的后缓冲区,等待屏幕的下一个垂直同步信号的到来,再显示到屏幕上。

SurfaceFlinger 负责合成所有的 Layer 并送显到 Display ,这些 Layer 主要有三种合成方式:

  • OpenGL ES:把这些图层合成到 FrameBuffer,然后把 FrameBuffer 提交给 hwcomposer 完成剩余合成和显示工作。

  • hwcomposer:通过 HWC 模块合成部分图层和 FrameBuffer,并显示到 Display。

  • Vulkan:把这些图层合成到 FrameBuffer,然后把 FrameBuffer 提交给 hwcomposer 完成剩余合成和显示工作。


OpenGL

传统的图形 API,规范了图形接口,Opengl ES 是一个专用于嵌入式设备的 OpenGL,但 Opengl 本身只提供接口和规范,具体的需要各平台提供接口层去适配自己的窗口体系,比如 Android 平台的 EGL。生态好,适用广泛。

Vulkan



Vulkan 是新一代的图形显示 API。也有业界称之为“下一代的 OpenGL”,是下一代高性能及精细化控制的开放的跨平台的图形 API。想要更深入了解的同学请参考我之前的文章: Vulkan-性能及精细化控制Vulkan-实践剖析

Vulkan 在 Android 7.0 后也被 google 支持了,Android 上分为三层结构对 Vulkan 进行了适配支持。

Vulkan 验证层:在 Vulkan 应用开发期间使用的库,用于查找应用在 Vulkan API 的使用方面的错误。在找出此类错误后,应移除这些库。

Vulkan 运行时:原生库 libvulkan.so 提供原生 Vulkan API。Vulkan 运行时的大部分功能由 GPU 供应商提供的驱动程序实现。Vulkan 运行时会封装驱动程序、提供 API 拦截功能(针对调试和其他开发者工具)以及管理驱动程序与平台依赖项之间的交互。

Vulkan 驱动程序:将 Vulkan API 映射到特定于硬件的 GPU 命令以及与内核图形驱动程序的交互。

Hardware Composer(硬件混合渲染器)

Android 中进行窗口(Layer)合成和显示的 HAL 层模块,显示子系统的硬件抽象实现。其内部实现是基于特定设备的,通常由屏幕硬件设备制造商 (OEM) 完成。主要用于确定合成缓冲区的最有效方式,SurfaceFlinger 在收集可见层的所有缓冲区后,便会询问 HWC 应如何进行合成。可分为 Client 合成和 Device 合成。SurfaceFlinger 可以将某些合成工作委托给 Hardware Composer,以分担 GPU 上的工作量。

HAL

硬件抽象层。HAL 提供标准接口,给更高级别的接口框架显示设备硬件功能。HAL 包含多个库模块,其中每个模块都为特定类型的硬件组件实现一组接口,例如相机或蓝牙等。当框架 API 请求访问设备硬件时,Android 系统将为该硬件加载相应的库模块。

Gralloc

含义是 Graphics Alloc 图形分配, 用于图形生产时请求分配内存.Android 系统在硬件抽象层中提供了一个 Gralloc 模块,封装了对 Framebuffer 的所有访问操作。

Gralloc 模块符合 Android 标准的 HAL 架构设计;它分为 fb 和 gralloc 两个设备:前者负责打开内核中的 Framebuffer 、初始化配置,以及提供 post, setSwapInterval 等操作;后者则管理帧缓冲区的分配和释放。

FrameBuffer

Linux 抽象出 FrameBuffer 这个设备来供用户态进程实现直接写屏。FrameBuffer 是显卡硬件的抽象,可以通过 FrameBuffer 的读写直接对显存进行操作。

FrameBuffer 本身不具备任何运算数据的能力,CPU 将运算后的结果放到 FrameBuffer,就会显示处理,中间不会对数据做处理。

Linux 内核提供了统一的 Framebuffer 显示驱动,节点为/dev/graphics/fb* 或者 /dev/fb* ,以 fb0 表示第一个 Monitor,这个虚拟设备将不同硬件厂商实现的真实设备统一在一个框架下,这样应用层就可以通过标准的接口进行图形/图像的输入和输出。

微信公众号首发,欢迎各位追求技术极致的coder关注:江湖修行。欢迎交流,转发,评论。

发布于: 2023-03-15阅读数: 16
用户头像

江湖修行

关注

还未添加个人签名 2021-12-05 加入

还未添加个人简介

评论

发布
暂无评论
Android图形渲染系统新_渲染_江湖修行_InfoQ写作社区