主要内容来自Source Android的主题内容图形篇
https://source.android.com/docs/core/graphics?hl=zh-cn
关键字:AOSP、Source、核心主题、图形、Surface、SurfaceFlinger
00. 概述
01. Android 图形组件
无论开发者使用什么渲染 API,一切内容都会渲染到 surface 上。Surface 表示缓冲区队列中的生产方,而缓冲区队列通常会被 SurfaceFlinger 消耗。在 Android 平台上创建的每个窗口都由 Surface 提供支持。所有被渲染的可见 Surface 都被 SurfaceFlinger 合成到屏幕。

图像流生产方
图像流生产方可以是生成图形缓冲区以供消耗的任何内容。例如 OpenGL ES、Canvas 2D 和 mediaserver 视频解码器。
图像流消耗方
图像流的最常见消耗方是 SurfaceFlinger,该系统服务会消耗当前可见的 Surface,并使用窗口管理器中提供的信息将它们合成到屏幕。SurfaceFlinger 是可以修改所显示部分内容的唯一服务。SurfaceFlinger 使用 OpenGL 和 Hardware Composer 来合成一组 Surface。
其他 OpenGL ES 应用也可以消耗图像流,例如相机应用会消耗相机预览图像流。非 GL 应用也可以是使用方,例如 ImageReader 类。
数据流
有关 Android 图形管道的描述,请参见下图:

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

BufferQueue 包含将图像流生产方与图像流消耗方结合在一起的逻辑。图像生产方的一些示例包括由相机 HAL 或 OpenGL ES 游戏生成的相机预览。图像消耗方的一些示例包括 SurfaceFlinger 或显示 OpenGL ES 流的另一个应用,如显示相机取景器的相机应用。
BufferQueue 是将缓冲区池与队列相结合的数据结构,它使用 Binder IPC 在进程之间传递缓冲区。生产方接口,或者您传递给想要生成图形缓冲区的某个人的内容,即是 IGraphicBufferProducer(SurfaceTexture 的一部分)。BufferQueue 通常用于渲染到 Surface,并且与 GL 消耗方及其他任务一起消耗内容。
BufferQueue 类将可生成图形数据缓冲区的组件(生产方)连接到接受数据以便进行显示或进一步处理的组件(使用方)。几乎所有在系统中移动图形数据缓冲区的内容都依赖于 BufferQueue。
12. BufferQueue 生产方和使用方(消耗方)
使用方(消耗方)创建并拥有 BufferQueue 数据结构,并且可存在于与其生产方不同的进程中。当生产方需要缓冲区时,它会通过调用 dequeueBuffer() 从 BufferQueue 请求一个可用的缓冲区,并指定缓冲区的宽度、高度、像素格式和用法标志。然后,生产方填充缓冲区并通过调用 queueBuffer() 将缓冲区返回到队列。接下来,使用方通过 acquireBuffer() 获取该缓冲区并使用该缓冲区的内容。当使用方操作完成后,它会通过调用 releaseBuffer() 将该缓冲区返回到队列。同步框架可控制缓冲区在 Android 图形管道中移动的方式。
BufferQueue 的一些特性(例如可以容纳的最大缓冲区数)由生产方和使用方联合决定。但是,BufferQueue 会根据需要分配缓冲区。除非特性发生变化,否则将会保留缓冲区;例如,如果生产方请求具有不同大小的缓冲区,系统会释放旧的缓冲区,并根据需要分配新的缓冲区。
BufferQueue 永远不会复制缓冲区内容,因为移动如此多的数据是非常低效的操作。相反,缓冲区始终通过句柄进行传递。
13. Gralloc
Gralloc的HIDL由AOSP定义,具体实现依赖供应商的内核驱动与显存管理
Gralloc 内存分配器会进行缓冲区分配,并通过两个特定于供应商的 HIDL 接口来进行实现(请参阅 hardware/interfaces/graphics/allocator/ 和 hardware/interfaces/graphics/mapper/)。allocate() 函数采用预期的参数(宽度、高度、像素格式)以及一组用法标志。
14. Gralloc分配器
Gralloc 分配器 HAL hardware/libhardware/include/hardware/gralloc.h 通过用法标志执行缓冲区分配。用法标志包括以下属性:
- 从软件 (CPU) 访问内存的频率
- 从硬件 (GPU) 访问内存的频率
- 是否将内存用作 OpenGL ES (GLES) 纹理
- 视频编码器是否会使用内存
例如,如果生产方的缓冲区格式指定 RGBA_8888 像素,并且生产方指明将从软件访问缓冲区(这意味着应用将在 CPU 上触摸像素),则 Gralloc 将按照 R-G-B-A 的顺序为每个像素创建 4 个字节的缓冲区。如果情况相反,生产方指明仅从硬件访问其缓冲区且缓冲区作为 GLES 纹理,Gralloc 可以执行 GLES 驱动程序所需的任何操作(比如 BGRA 排序、非线性搅和布局和替代颜色格式等)。允许硬件使用其首选格式可以提高性能。
某些值在特定平台上无法组合。例如,视频编码器标志可能需要 YUV 像素,因此将无法添加软件访问权限并指定 RGBA_8888。
Gralloc 返回的句柄可以通过 Binder 在进程之间进行传递。
15. 受保护的缓冲区
Gralloc 用法标志 GRALLOC_USAGE_PROTECTED 允许仅通过受硬件保护的路径显示图形缓冲区。这些叠加平面是显示 DRM 内容的唯一途径(SurfaceFlinger 或 OpenGL ES 驱动程序无法访问受 DRM 保护的缓冲区)。
受 DRM 保护的视频只能在叠加平面上呈现。支持受保护内容的视频播放器必须使用 SurfaceView 实现。在不受保护的硬件上运行的软件无法读取或写入缓冲区;受硬件保护的路径必须显示在硬件混合渲染器叠加层上(也就是说,如果硬件混合渲染器切换到 OpenGL ES 合成,受保护的视频将从屏幕中消失)。
如需详细了解受保护的内容,请参阅 DRM。
02. 在 Android 12 中实现 DMABUF 和 GPU 内存计算
Android 12把以 DMABUF 为载体的图形缓冲(相机帧、视频帧、GL 纹理/FBO、AHardwareBuffer 等)更统一、更精确地“计入”到具体进程的内存账目里,并让系统内存管理(LMKD、memcg/PSI)据此做更合理的杀进程与资源回收决策。
在 Android 12 之前,并不是“完全不计算”,而是“计算不完整、归属不统一、设备依赖性强”。很多显存/图形缓冲不进入 PSS/RSS,memtrack 也常受限于厂商实现,因此系统对谁占了多少图形内存“不够看得见”,导致内存压力判断与杀进程不够准确。
提高 RAM 损失计算的准确性
过去,RAM 损失的计算方式如下:
final long lostRAM = memInfo.getTotalSizeKb() - (totalPss - totalSwapPss)
memInfo.getFreeSizeKb()-memInfo.getCachedSizeKb()**kernelUsed**-memInfo.getZramTotalSizeKb();
totalPss 组件包含 GPU 内存用量,后者由 Memtrack HAL 的 getMemory() 接口返回。kernelUsed 组件包含 DMA-BUF 总内存用量。不过,对于 Android 设备,GPU 内存源自下列各项:
- 由 GPU 驱动程序使用物理页面分配器进行的直接分配
- 映射到 GPU 地址空间的 DMA-BUF
因此,在计算 RAM 损失时,系统会将内存映射到 GPU 地址空间的 DMA-BUFF 减去两次。Android 12 实施了一个解决方案,可以计算映射到 GPU 地址空间的 DMA-BUF 的大小,这意味着它在 RAM 损失计算中只计算一次。
该解决方案的详细信息如下:
- 在使用 PID 0 进行调用时,Memtrack HAL API
getMemory()必须为 MemtrackType::GL 和 MemtrackRecord::FLAG_SMAPS_UNACCOUNTED 报告 GPU 全局专用总内存。 - 在使用
PID0为MemtrackType(而不是GL)进行调用时,getMemory() 不得失败,而必须返回 0。 - 在 Android 12 中添加的 GPU 内存跟踪点/eBPF 解决方案会占用 GPU 总内存。从 GPU 总内存中减去 GPU 专用总内存,即可得出映射到 GPU 地址空间的 DMA-BUF 的大小。然后,通过正确计算 GPU 内存用量,这个值可以用来提高 RAM 损失计算的准确性。
- GPU 专用内存包含在大多数 Memtrack HAL 实现的
totalPss中,因此必须先删除其中的重复信息,然后才能将其从lostRAM中移除。
03. Surface 和 SurfaceHolde
Surface 对象使应用能够渲染要在屏幕上显示的图像。通过 SurfaceHolder 接口,应用可以编辑和控制 Surface。
31. Surface
Surface 是一个接口,供生产方与消耗方交换缓冲区。
用于显示 Surface 的 BufferQueue 通常配置为三重缓冲。缓冲区是按需分配的,因此,如果生产方足够缓慢地生成缓冲区(例如在 60 fps 的显示屏上以 30 fps 的速度缓冲),队列中可能只有两个分配的缓冲区。按需分配缓冲区有助于最大限度地减少内存消耗。您可以在 dumpsys SurfaceFlinger 的输出中看到每个层级关联的缓冲区的摘要。
大多数客户端使用 OpenGL ES 或 Vulkan 渲染到 Surface 上。但是,有些客户端使用画布渲染到 Surface 上。
画布渲染
画布实现由 Skia 图形库提供。如果您要绘制一个矩形,可以调用 Canvas API,它会在缓冲区中适当地设置字节。为了确保两个客户端不会同时更新某个缓冲区,或者在该缓冲区正在被显示时写入该缓冲区,请锁定该缓冲区以进行访问。您可以使用以下命令处理画布锁:
-
lockCanvas()可锁定缓冲区以在 CPU 上渲染,并返回用于绘图的画布。 -
unlockCanvasAndPost()可解锁缓冲区并将其发送到合成器。 -
lockHardwareCanvas()可锁定缓冲区以在 GPU 上渲染,并返回用于绘图的画布。
注意:当应用通过 lockCanvas() 锁定 Surface 时,所获得的画布一概不会获得硬件加速。
生产方首次从 BufferQueue 请求某个缓冲区时,该缓冲区将被分配并初始化为零。必须进行初始化,以避免意外地在进程之间共享数据。但是,如果您重复使用缓冲区,以前的内容仍会存在。如果您反复调用 lockCanvas() 和 unlockCanvasAndPost() 而不绘制任何内容,则生产方会在先前渲染的帧之间循环。
Surface 锁定/解锁代码会保留对先前渲染的缓冲区的引用。如果在锁定 Surface 时指定了脏区域,那么它将从以前的缓冲区复制非脏像素。SurfaceFlinger 或 HWC 通常会处理缓冲区;但是由于我们只需从缓冲区中读取内容,因此无需等待独占访问权。
32. SurfaceHolder
SurfaceHolder 是系统用于与应用共享 Surface 所有权的接口。与 Surface 配合使用的一些客户端需要 SurfaceHolder,因为用于获取和设置 Surface 参数的 API 是通过 SurfaceHolder 实现的。一个 SurfaceView 包含一个 SurfaceHolder。
与 View 交互的大多数组件都涉及到 SurfaceHolder。一些其他 API(如 MediaCodec)将在 Surface 本身上运行。
04. SurfaceFlinger 和 WindowManager
SurfaceFlinger 接受缓冲区,对它们进行合成,然后发送到屏幕。WindowManager 为 SurfaceFlinger 提供缓冲区和窗口元数据,而 SurfaceFlinger 可使用这些信息将 Surface 合成到屏幕。
41. SurfaceFlinger
SurfaceFlinger 可通过两种方式接受缓冲区:通过 BufferQueue 和 SurfaceControl,或通过 ASurfaceControl。
SurfaceFlinger 接受缓冲区的一种方式是通过 BufferQueue 和 SurfaceControl。当应用进入前台时,它会从 WindowManager 请求缓冲区。然后,WindowManager 会从 SurfaceFlinger 请求层。层是 surface(包含 BufferQueue)和 SurfaceControl(包含显示框架等层元数据)的组合。SurfaceFlinger 创建层并将其发送至 WindowManager。然后,WindowManager 将 Surface 发送至应用,但会保留 SurfaceControl 来操控应用在屏幕上的外观。
虽然应用可以随时提交缓冲区,但 SurfaceFlinger 仅能在屏幕处于两次刷新之间时唤醒,以接受缓冲区,这会因设备而异。这样可以最大限度地减少内存使用量,并避免屏幕上出现可见的撕裂现象(如果显示内容在刷新期间更新,则会出现此现象)。
在屏幕处于两次刷新之间时,屏幕会向 SurfaceFlinger 发送 VSYNC 信号。VSYNCVSYNC 信号表明可对屏幕进行刷新而不会产生撕裂。当 SurfaceFlinger 接收到 VSYNC 信号后,SurfaceFlinger 会遍历其层列表,以查找新的缓冲区。如果 SurfaceFlinger 找到新的缓冲区,SurfaceFlinger 会获取缓冲区;否则,SurfaceFlinger 会继续使用上一次获取的那个缓冲区。SurfaceFlinger 必须始终显示内容,因此它会保留一个缓冲区。如果在某个层上没有提交缓冲区,则该层会被忽略。
SurfaceFlinger 在收集可见层的所有缓冲区之后,便会询问硬件混合渲染器 (HWC) 应如何进行合成。如果 HWC 将层合成类型标记为客户端合成,则 SurfaceFlinger 将合成这些层。然后,SurfaceFlinger 会将输出缓冲区传递给 HWC。
42. WindowManager
WindowManager 会控制 window 对象,它们是用于容纳 view 对象的容器。window 对象始终由 surface 对象提供支持。WindowManager 会监督生命周期、输入和聚焦事件、屏幕方向、转换、动画、位置、变形、Z 轴顺序以及窗口的许多其他方面。WindowManager 会将所有窗口元数据发送到 SurfaceFlinger,以便 SurfaceFlinger 可以使用这些数据在屏幕上合成 Surface。
05. HWC 硬件混合渲染器 HAL
硬件混合渲染器 (HWC) HAL 用于确定通过可用硬件来合成缓冲区的最有效方法。
当您考虑使用叠加平面时,很容易发现这种方法的好处,它会在显示硬件(而不是 GPU)中合成多个缓冲区。例如,假设有一部普通 Android 手机,其屏幕方向为纵向,状态栏在顶部,导航栏在底部,其他区域显示应用内容。每个层的内容都在单独的缓冲区中。您可以使用以下任一方法处理合成:
- 将应用内容渲染到暂存缓冲区中,然后在其上渲染状态栏,再在其上渲染导航栏,最后将暂存缓冲区传送到显示硬件。
- 将三个缓冲区全部传送到显示硬件,并指示它从不同的缓冲区读取屏幕不同部分的数据。
后一种方法可以显著提高效率。
显示处理器功能差异很大。叠加层的数量(无论层是否可以旋转或混合)以及对定位和重叠的限制很难通过 API 表达。为了适应这些选项,HWC 会执行以下计算:
- SurfaceFlinger 向 HWC 提供一个完整的层列表,并询问“您希望如何处理这些层?”
- HWC 的响应方式是将每个层标记为设备或客户端合成。
- SurfaceFlinger 会处理所有客户端,将输出缓冲区传送到 HWC,并让 HWC 处理其余部分。
由于硬件供应商可以定制决策代码,因此可以在每台设备上实现最佳性能。
当屏幕上的内容没有变化时,叠加平面的效率可能会低于 GL 合成。当叠加层内容具有透明像素且叠加层混合在一起时,尤其如此。在此类情况下,HWC 可以为部分或全部层请求 GLES 合成,并保留合成的缓冲区。如果 SurfaceFlinger 要求合成同一组缓冲区,HWC 可以显示先前合成的暂存缓冲区。这可以延长闲置设备的电池续航时间。
Android 设备通常支持 4 个叠加平面。尝试合成的层数多于叠加层数会导致系统对其中一些层使用 GLES 合成,这意味着应用使用的层数会对能耗和性能产生重大影响。
51. 屏幕合成操作
如果 SurfaceFlinger 具有可合成的新内容,则会唤醒,且每个 VSYNC 唤醒一次。该新内容可以是来自应用的新图像缓冲区,也可以是一个或多个图层的属性更改。当 SurfaceFlinger 唤醒时,它将执行以下步骤:
处理事务(如果存在)。
如果存在新的图形缓冲区,则将其锁定。
如果步骤 1 或 2 导致显示内容更改,则执行新的合成。
为了执行新的合成,SurfaceFlinger 会创建和销毁图层或修改图层状态(如适用)。它还会使用 setLayerBuffer 或 setLayerColor 等调用,用图层的当前内容来更新图层。在更新所有图层之后,SurfaceFlinger 会调用 validateDisplay,以告知 HWC 检查各个图层的状态,并确定如何进行合成。尽管在某些情况下,SurfaceFlinger 会通过 GPU 回退来合成图层,但在默认情况下,SurfaceFlinger 会尝试配置每个图层,以使相应图层由 HWC 进行合成。
在调用 validateDisplay 之后,SurfaceFlinger 会调用 getChangedCompositionTypes,以查看 HWC 是否需要在执行合成之前更改任何图层的合成类型。如需接受这些更改,SurfaceFlinger 需要调用 acceptDisplayChanges。
如果已将任何图层标记为进行 SurfaceFlinger 合成,SurfaceFlinger 会将这些图层合成到目标缓冲区中。然后,SurfaceFlinger 通过调用 setClientTarget 将该缓冲区提供给屏幕,以便缓冲区可以在屏幕上显示,或者进一步与未标记为进行 SurfaceFlinger 合成的图层合成。如果没有将任何图层标记为进行 SurfaceFlinger 合成,则 SurfaceFlinger 会跳过合成步骤。
最后,SurfaceFlinger 会调用 presentDisplay,以告知 HWC 完成合成过程并显示最终结果。
同步栅栏
同步栅栏是 Android 图形系统的关键部分。栅栏允许 CPU 工作与并行的 GPU 工作相互独立进行,仅在存在真正的依赖关系时才会阻塞。
例如,当应用提交在 GPU 上生成的缓冲区时,它还将提交一个同步栅栏对象。当 GPU 完成写入缓冲区的操作时,该栅栏会变为有信号状态。
HWC 要求 GPU 在显示缓冲区之前完成写入缓冲区的操作。同步栅栏通过包含缓冲区的图形管道传递,并在缓冲区写入完成时发出信号。在显示缓冲区之前,HWC 会检查同步栅栏是否已发出信号,如果是,则显示缓冲区。
06. 层和显示屏
层是合成的最重要单元。层是 Surface 和 SurfaceControl 实例的组合。每个层都有一组属性,用于定义它与其他层的交互方式。层属性如下表所述。

61. ScreenRecord
screenrecord 命令可让用户将屏幕上显示的所有内容作为一个 .mp4 文件记录在磁盘上。为此,系统从 SurfaceFlinger 接收合成的帧,将它们写入视频编码器,然后将已编码的视频数据写入一个文件。视频编解码器由单独的进程 (mediaserver) 进行管理,因此我们必须在系统中移动大量图形缓冲区。为了使其更具挑战性,我们的目标是以全分辨率录制 60 fps 的视频。高效完成这项工作的关键是 BufferQueue。
MediaCodec 类允许应用以缓冲区中的原始字节形式或通过 Surface 来提供数据。当 screenrecord 请求访问视频编码器时,mediaserver 进程会创建一个 BufferQueue,将其自身连接到使用方端,然后将生产方端作为 Surface 传回到 screenrecord。
然后,screenrecord 实用程序会要求 SurfaceFlinger 创建一个镜像主屏幕的虚拟屏幕(即它与主屏幕具有完全相同的层),并指示它将输出发送到来自 mediaserver 进程的 Surface。在这种情况下,SurfaceFlinger 是缓冲区的生产方,而不是使用方。
配置完成后,screenrecord 会在编码数据显示时触发。在应用绘制时,其缓冲区会前往 SurfaceFlinger,SurfaceFlinger 将它们合成为单个缓冲区,然后直接发送到 mediaserver 进程中的视频编码器。screenrecord 进程从未观测到完整的帧。在内部,mediaserver 进程具有自己的移动缓冲区的方式,这种方式还通过句柄传递数据,从而最大限度地降低开销。
07. VSync
VSYNC 信号可同步显示管道。显示流水线由应用渲染、SurfaceFlinger 合成以及用于在屏幕上显示图像的硬件混合渲染器 (HWC) 组成。VSYNC 可同步应用唤醒以开始渲染的时间、SurfaceFlinger 唤醒以合成屏幕的时间以及屏幕刷新周期。这种同步可以消除卡顿,并提升图形的视觉表现。
HWC 可生成 VSYNC 事件并通过回调将事件发送到 SurfaceFlinger:
typedef void (*HWC2_PFN_VSYNC)(hwc2_callback_data_t callbackData,
hwc2_display_t display, int64_t timestamp);
SurfaceFlinger 通过调用 setVsyncEnabled 来控制 HWC 是否生成 VSYNC 事件。SurfaceFlinger 使 setVsyncEnabled 能够生成 VSYNC 事件,因此它可以与屏幕的刷新周期同步。当 SurfaceFlinger 同步到屏幕刷新周期时,SurfaceFlinger 会停用 setVsyncEnabled 以阻止 HWC 生成 VSYNC 事件。如果 SurfaceFlinger 检测到实际 VSYNC 与它先前建立的 VSYNC 之间存在差异,则 SurfaceFlinger 会重新启动 VSYNC 事件生成过程。
VSYNC 偏移
相位偏移就是“相对于下一次物理 VSYNC”的提早或延后量(通常是提早),用来给不同角色预留工作时间。
DispSync 会为注册者计算出“预测 VSYNC 时间 − 该注册者的偏移量”的时刻,并在这时唤醒/回调他们:
应用侧(App/Choreographer/RenderThread)的 VSYNC 通常更早,让应用尽快开始绘制并提交缓冲。
SurfaceFlinger 的 VSYNC 稍晚一些(但仍早于物理 VSYNC),在接近截止时间完成合成并交给 HWC。
这样就形成“应用先画、SF后合成、下一次物理 VSYNC 正好显示”的流水线,既减少丢帧又降低端到端延迟。
08. Frame pacing
Android Frame Pacing 库(也称为 Swappy)是 Android Game SDK 的一部分。它可帮助 OpenGL 和 Vulkan 游戏在 Android 上实现流畅的渲染和正确的帧同步。
帧同步是指游戏的逻辑和渲染循环与操作系统的显示子系统和底层显示硬件之间的同步。Android 显示子系统旨在避免某些视觉伪影,例如画面撕裂。显示子系统可通过执行以下操作避免画面撕裂:
- 在内部缓冲之前的帧
- 检测延迟帧的提交情况
- 当检测到延迟帧时继续显示当前帧
帧展示时间不一致是因为游戏渲染循环的运行速率与本机显示硬件支持的速率不同。
09. 多种刷新率
Android 11 增加了对具有多种刷新率的设备的支持。此功能包含三个主要组成部分:
- android.hardware.graphics.composer@2.4 中引入的新 HAL API。
- 平台代码,用于解析不同刷新率的设备配置并设置所需的刷新率
- 新增的 SDK 和 NDK API,使应用可以设置所需的帧速率
DisplayManager 设置政策后,SurfaceFlinger 会根据活跃层(将帧更新排入队列的层)设置刷新率。如果该层的所有者设置了帧速率,则 SurfaceFlinger 会尝试将刷新率设置为该帧速率的倍数。 例如,如果两个活跃层的帧速率设置为 24 和 60,则 SurfaceFlinger 会选择 120Hz(如果可用)。如果 SurfaceFlinger 无法使用此类刷新率,则会尝试选择对帧速率来说误差最小的刷新率。如需了解详情,请参阅 developer.android.com 上的开发者文档
SurfaceFlinger 维护以下标志来控制刷新率的确定方式:
-
ro.surface_flinger.use_content_detection_for_refresh_rate:如果已设置,系统会根据活跃层确定刷新率,即使未设置帧速率。SurfaceFlinger 持续运用启发法,通过关注连接到缓冲区的呈现时间戳,找出该层发布缓冲区的平均 fps。 -
ro.surface_flinger.set_touch_timer_ms:如果大于 0,则在配置的超时时间内有用户轻触屏幕时,将使用默认刷新率。此启发法完成时,便会对动画采用默认刷新率。 -
ro.surface_flinger.set_idle_timer_ms:如果大于 0,则在配置的超时时间内没有屏幕更新时,将使用最小刷新频率。 -
ro.surface_flinger.set_display_power_timer_ms:如果大于 0,则在配置的超时时间内开启屏幕(或退出 AOD)时,将使用默认刷新率。
Android15开始支持自适应刷新率。
10. EGLSurface 和 OpenGL ES以及Vulkan,同步框架
实现 OpenGL ES 和 EGL、实现 Vulkan
https://source.android.com/docs/core/graphics/implement-opengl-es?hl=zh-cn
https://source.android.com/docs/core/graphics/implement-vulkan?hl=zh-cn
https://source.android.com/docs/core/graphics/sync?hl=zh-cn
ANativeWindow
公开的 Surface 类以 Java 编程语言实现。C/C++ 中的同等项是 ANATIONWindow 类,由 Android NDK 半公开。您可以使用 ANativeWindow_fromSurface() 调用从 Surface 获取 ANativeWindow。就像它的 Java 语言同等项一样,您可以对 ANativeWindow 进行锁定、以软件形式进行渲染,以及解锁并发布。基本的“原生窗口”类型是 BufferQueue 的生产方端。
如需从原生代码创建 EGL 窗口 Surface,可将 EGLNativeWindowType 的实例传递到 eglCreateWindowSurface()。EGLNativeWindowType 是 ANativeWindow 的同义词,因此可以互换使用。
OpenGLRenderer (libhwui) 属性
本文档将列出您可以用来控制 Android 的 2D 硬件加速渲染管道的所有属性。将 device.mk 中的这些属性设置为 PRODUCT_PROPERTY_OVERRIDES。
“OpenGLRenderer”这个日志标签和历史名字不代表今天一定用的是 OpenGL。libhwui 现在的绘制引擎是 Skia,Skia 的 GPU 后端在 Android 上可以是 OpenGL ES(SkiaGL)或 Vulkan(SkiaVulkan)。
也就是说:hwui 通常依赖 Skia 的 GPU 后端;多数设备默认为 SkiaGL(OpenGL ES),部分新设备或厂商配置为 SkiaVulkan。Skia 也有纯 CPU 后端,但 UI 硬件加速场景走的是 GPU 后端。