每个开发人员都应该了解有关 Surface、SurfaceHolder、EGLSurface、SurfaceView、GLSurfaceView、SurfaceTexture、TextureView、SurfaceFlinger 和 Vulkan 的知识。
本页介绍了 Android 系统级图形架构的基本元素以及应用程序框架和多媒体系统如何使用它们。重点是图形数据缓冲区如何在系统中移动。如果您想知道为什么 SurfaceView 和 TextureView 的行为方式如此,或者表面和 EGLSurface 如何交互,那么您来对地方了。
假设您对 Android 设备和应用程序开发有一定的了解。您不需要了解应用程序框架的详细知识,并且很少提及 API 调用,但该材料不会与其他公共文档重叠。目标是提供渲染输出帧所涉及的重要事件的详细信息,以帮助您在设计应用程序时做出明智的选择。为了实现这一点,我们从下往上工作,描述 UI 类如何工作,而不是如何使用它们。
本节包括几个页面,涵盖从背景材料到 HAL 详细信息再到用例的所有内容。它首先解释 Android 图形缓冲区,描述合成和显示机制,然后继续介绍为合成器提供数据的更高级别的机制。我们建议按下面列出的顺序阅读页面,而不是跳到听起来有趣的主题。
低级组件
- BufferQueue 和 gralloc 。 BufferQueue 将生成图形数据缓冲区的对象(生产者)连接到接受数据以进行显示或进一步处理的对象(消费者)。缓冲区分配是通过gralloc内存分配器执行的,该分配器通过供应商特定的 HAL 接口实现。
- SurfaceFlinger、Hardware Composer 和虚拟显示器。 SurfaceFlinger 接受来自多个源的数据缓冲区,将它们组合起来,然后将它们发送到显示器。硬件合成器 HAL (HWC) 确定将缓冲区与可用硬件进行合成的最有效方法,并且虚拟显示器使合成输出在系统内可用(记录屏幕或通过网络发送屏幕)。
- Surface、画布和 SurfaceHolder 。 Surface 会生成一个经常被 SurfaceFlinger 使用的缓冲区队列。当渲染到表面上时,结果最终会存储在缓冲区中并发送给消费者。 Canvas API 提供了直接在表面上绘图的软件实现(具有硬件加速支持)(OpenGL ES 的低级替代方案)。与视图有关的任何内容都涉及 SurfaceHolder,其 API 可以获取和设置表面参数,例如大小和格式。
- EGLSurface 和 OpenGL ES 。 OpenGL ES (GLES)定义了一个图形渲染 API,旨在与EGL结合使用,EGL 是一个可以通过操作系统创建和访问窗口的库(要绘制纹理多边形,请使用 GLES 调用;要将渲染放在屏幕上,请使用 EGL 调用)。本页还介绍了 ANativeWindow,它是 Java Surface 类的 C/C++ 等效项,用于从本机代码创建 EGL 窗口表面。
- 伏尔甘。 Vulkan 是一种低开销、跨平台的 API,用于高性能 3D 图形。与 OpenGL ES 一样,Vulkan 提供了在应用程序中创建高质量实时图形的工具。 Vulkan 的优势包括减少 CPU 开销以及支持SPIR-V 二进制中间语言。
高级组件
- SurfaceView 和 GLSurfaceView 。 SurfaceView 结合了表面和视图。 SurfaceView 的视图组件由 SurfaceFlinger(而不是应用程序)合成,从而能够从单独的线程/进程进行渲染,并与应用程序 UI 渲染隔离。 GLSurfaceView 提供帮助程序类来管理 EGL 上下文、线程间通信以及与活动生命周期的交互(但不需要使用 GLES)。
- 表面纹理。 SurfaceTexture 结合了表面和 GLES 纹理来创建一个 BufferQueue,您的应用程序是该 BufferQueue 的使用者。当生产者对新缓冲区进行排队时,它会通知您的应用程序,您的应用程序会释放先前持有的缓冲区,从队列中获取新缓冲区,并进行 EGL 调用以使该缓冲区可作为外部纹理供 GLES 使用。 Android 7.0 添加了对安全纹理视频播放的支持,从而可以对受保护的视频内容进行 GPU 后处理。
- 纹理视图。 TextureView 将视图与 SurfaceTexture 组合在一起。 TextureView 包装了一个 SurfaceTexture 并负责响应回调并获取新的缓冲区。绘制时,TextureView 使用最近接收到的缓冲区的内容作为其数据源,在视图状态指示的任何位置和方式进行渲染。视图合成始终使用 GLES 执行,这意味着内容更新也可能导致其他视图元素重绘。