图形架构

每位开发者都应了解的关于 Surface、SurfaceHolder、EGLSurface、SurfaceView、GLSurfaceView、SurfaceTexture、TextureView、SurfaceFlinger 和 Vulkan 的知识。

本页介绍了 Android 系统级图形架构的基本要素,以及应用框架和多媒体系统如何使用它们。重点是图形数据缓冲区如何在系统中移动。如果您曾经想知道 SurfaceView 和 TextureView 的行为方式,或者 Surface 和 EGLSurface 如何交互,那么您来对地方了。

假定您对 Android 设备和应用开发有一定的了解。您无需详细了解应用框架,并且很少提及 API 调用,但本材料与其他公共文档不重叠。目标是提供有关渲染帧以输出的重大事件的详细信息,以帮助您在设计应用时做出明智的选择。为了实现这一目标,我们自下而上地工作,描述 UI 类的工作方式,而不是它们的使用方式。

本节包含多个页面,涵盖从背景材料到 HAL 详细信息再到用例的所有内容。它首先解释 Android 图形缓冲区,描述合成和显示机制,然后继续介绍为合成器提供数据的高级机制。我们建议按下列顺序阅读页面,而不是跳到听起来有趣的主题。

底层组件

  • BufferQueue 和 gralloc。BufferQueue 将生成图形数据缓冲区的东西(生产者)连接到接受数据以进行显示或进一步处理的东西(消费者)。缓冲区分配通过 gralloc 内存分配器执行,该分配器通过特定于供应商的 HAL 接口实现。
  • SurfaceFlinger、硬件合成器和虚拟显示。SurfaceFlinger 接受来自多个数据源的缓冲区,将它们合成,然后发送到显示器。硬件合成器 HAL (HWC) 确定使用可用硬件合成缓冲区的最有效方法,虚拟显示使合成后的输出在系统内可用(录制屏幕或通过网络发送屏幕)。
  • Surface、画布和 SurfaceHolder。Surface 生成一个缓冲区队列,该队列通常被 SurfaceFlinger 消耗。当在 Surface 上渲染时,结果最终会出现在一个缓冲区中,该缓冲区被发送给消费者。Canvas API 提供了一个软件实现(具有硬件加速支持),用于直接在 Surface 上绘图(OpenGL ES 的低级替代方案)。任何与视图相关的内容都涉及 SurfaceHolder,其 API 允许获取和设置 Surface 参数,例如大小和格式。
  • EGLSurface 和 OpenGL ESOpenGL ES (GLES) 定义了一个图形渲染 API,旨在与 EGL 结合使用,EGL 是一个可以通过操作系统创建和访问窗口的库(要绘制纹理多边形,请使用 GLES 调用;要将渲染放到屏幕上,请使用 EGL 调用)。此页面还介绍了 ANativeWindow,它是 Java Surface 类的 C/C++ 等效类,用于从原生代码创建 EGL 窗口 Surface。
  • Vulkan。Vulkan 是一个用于高性能 3D 图形的低开销、跨平台 API。与 OpenGL ES 类似,Vulkan 提供了在应用程序中创建高质量、实时图形的工具。Vulkan 的优势包括降低 CPU 开销以及支持 SPIR-V 二进制中间语言。

高级组件

  • SurfaceView 和 GLSurfaceView。SurfaceView 结合了 Surface 和视图。SurfaceView 的视图组件由 SurfaceFlinger(而不是应用程序)合成,从而可以从单独的线程/进程进行渲染,并与应用程序 UI 渲染隔离。GLSurfaceView 提供了帮助程序类来管理 EGL 上下文、线程间通信以及与活动生命周期的交互(但不是使用 GLES 所必需的)。
  • SurfaceTexture。SurfaceTexture 结合了 Surface 和 GLES 纹理,以创建一个 BufferQueue,其中您的应用程序是消费者。当生产者将新缓冲区排队时,它会通知您的应用程序,然后您的应用程序释放先前持有的缓冲区,从队列中获取新缓冲区,并进行 EGL 调用以使缓冲区作为外部纹理可用于 GLES。Android 7.0 增加了对安全纹理视频播放的支持,从而可以对受保护的视频内容进行 GPU 后处理。
  • TextureView。TextureView 结合了视图和 SurfaceTexture。TextureView 封装了 SurfaceTexture,并负责响应回调和获取新缓冲区。绘制时,TextureView 使用最近接收到的缓冲区的内容作为其数据源,在视图状态指示的位置和方式进行渲染。视图合成始终使用 GLES 执行,这意味着内容更新可能会导致其他视图元素也重新绘制。