Android 图形系统之五:Gralloc

Gralloc (Graphics Allocator) 是 Android 系统中的关键组件之一,用于管理图形缓冲区的分配、映射以及处理。在 Android 的图形架构中,Gralloc 充当了 HAL (Hardware Abstraction Layer) 的一部分,为系统和硬件提供了通用的接口,使应用程序能够高效地处理图形数据。

Gralloc 的主要功能

Gralloc 的功能可以划分为以下几个核心部分:

1. 图形缓冲区分配

  • 目标:为应用程序或系统组件分配物理内存,用于存储显示图形数据。
  • 细节 :缓冲区的分配依据 宽度、高度、像素格式使用场景 (Usage Flags)。显存分配通常由底层 GPU 或特定硬件模块管理。

2. 内存映射

  • 目标:通过映射将物理内存的缓冲区暴露给用户态程序。
  • 细节:映射操作将内存映射到调用进程的虚拟地址空间。支持映射为 CPU 可访问的地址(用户态程序可直接操作数据)。

3. 跨进程共享

  • 目标:缓冲区能在不同进程间高效传递。
  • 细节:Gralloc 使用文件描述符 (FD) 作为缓冲区的共享句柄。通过 binder 或其他机制,FD 可在生产者和消费者之间传递,无需拷贝数据。

4. 缓冲区属性管理

  • 目标:为缓冲区附加元数据,描述缓冲区的用途和限制。
  • 细节 :包括 像素格式 (RGB、YUV 等)、宽高尺寸使用标志(Usage Flags)等。这些属性会影响底层驱动分配显存的策略。

Gralloc 的架构设计

Gralloc 的架构可以分为以下几个层次:

1. 高层:应用程序接口

  • 上层应用通常通过图形库(如 OpenGL ES、Vulkan)或 Android 提供的 UI 组件(如 SurfaceView、TextureView)使用 Gralloc。
  • 示例:OpenGL ES 使用 GPU 渲染后,需要通过 Gralloc 分配的缓冲区将结果共享到显示层。视频解码时,MediaCodec 使用 Gralloc 分配的缓冲区存储解码后的帧。

2. 中间层:Framework 和 HAL

  • Gralloc HAL提供抽象接口,屏蔽硬件细节,支持多种硬件实现。HAL 的接口通过 allocator 和 mapper 提供主要功能:IGraphicBufferAllocator:缓冲区分配接口。IGraphicBufferMapper:缓冲区映射、属性管理和释放接口。HAL 的实现位于 /hardware/interfaces/graphics/。
  • BufferQueue****BufferQueue 是 Android 图形堆栈的核心组件,管理生产者(Producer)和消费者(Consumer)之间的缓冲区流转。生产者使用 Gralloc 分配缓冲区后,交由消费者处理。BufferQueue 通过 Binder IPC 支持跨进程通信。

3. 底层:驱动与硬件

  • Gralloc 的底层实现依赖硬件供应商提供的驱动支持:显存分配:显存通常由 GPU 驱动分配。DMA 支持:某些硬件支持通过 DMA 直接访问内存。Cache 操作:确保 CPU 和 GPU 对缓冲区的访问保持一致。
  • 映射内存管理内存映射需要确保多进程、多设备的一致性,通常通过内核接口(如 mmap)实现。

Gralloc 的关键组件

1. GraphicBuffer
  • 它是 Android Framework 中用于表示图形缓冲区的核心类,封装了分配、引用和访问缓冲区的功能。
cpp 复制代码
sp buffer = new GraphicBuffer(width, height, format, usage);
2. BufferQueue
  • BufferQueue 是 Android 图形堆栈的核心组件之一,负责管理生产者(Producer)和消费者(Consumer)之间的缓冲区传递。
3. Buffer 分配策略

Gralloc 的分配通常基于以下参数:

  • 大小(宽度和高度)
  • 格式(如 RGB、YUV)
  • 用途(Usage Flags,例如 CPU/GPU 读取或写入)

示例 Usage Flags

  • GRALLOC_USAGE_SW_READ_OFTEN:缓冲区需要频繁被软件读取。
  • GRALLOC_USAGE_HW_TEXTURE:缓冲区用作 GPU 纹理。

数据流分析

以应用程序绘制一帧图像到屏幕为例,Gralloc 的典型数据流如下:

  1. 分配缓冲区
    • 应用通过 SurfaceFlinger 或其他接口请求分配图形缓冲区。
    • SurfaceFlinger 调用 Gralloc HAL 完成分配。
    • 分配的缓冲区封装为 GraphicBuffer。
  2. 写入缓冲区
    • 生产者(如 GPU)通过 OpenGL/Vulkan API 渲染到缓冲区。
    • Gralloc 确保缓冲区内存可被写入。
  3. 共享缓冲区
  • 渲染完成后,缓冲区通过 BufferQueue 提供给消费者。
  • 消费者可以是显示系统(如 SurfaceFlinger)或其他应用程序。
  1. 释放缓冲区
    • 使用完成后,缓冲区由 Gralloc HAL 释放,回收资源。

Gralloc 的具体实现

1. Gralloc HAL 接口

接口定义

Gralloc HAL 主要接口位于 /hardware/interfaces/graphics/allocator/hardware/interfaces/graphics/mapper 中,定义如下:

  • IGraphicBufferAllocator:分配缓冲区
cpp 复制代码
// allocator.hal
virtual Error allocate(
    uint32_t width, uint32_t height, PixelFormat format,
    uint64_t usage, uint32_t stride, buffer_handle_t* handle) = 0;
  • IGraphicBufferMapper:映射和管理缓冲区
cpp 复制代码
// mapper.hal
virtual Error lock(
    buffer_handle_t buffer, uint64_t usage,
    const Rect& accessRegion, void** outData) = 0;

virtual Error unlock(buffer_handle_t buffer) = 0;

2. GraphicBuffer 类

GraphicBuffer 是 Android Framework 层对 Gralloc 分配的缓冲区的封装,定义在 /frameworks/native/libs/ui/GraphicBuffer.h

构造函数示例

cpp 复制代码
GraphicBuffer::GraphicBuffer(
    uint32_t width, uint32_t height, PixelFormat format, uint32_t usage)
{
    sp allocator = GraphicBufferAllocator::get();
    allocator->allocate(width, height, format, usage, &mHandle, &mStride);
}

代码示例

以下是使用 Gralloc HAL 分配缓冲区的代码示例:

cpp 复制代码
#include 
#include 

const hw_module_t* module;
gralloc_module_t* gralloc;
buffer_handle_t buffer;
int stride;
void* mappedData;

// 初始化 Gralloc 模块
if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {
    gralloc = reinterpret_cast(module);

    // 分配缓冲区
    gralloc->alloc(gralloc, 1920, 1080, HAL_PIXEL_FORMAT_RGBA_8888,
                   GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
                   &buffer, &stride);

    // 映射缓冲区
    gralloc->lock(gralloc, buffer, GRALLOC_USAGE_SW_WRITE_OFTEN, 0, 0, 1920, 1080, &mappedData);

    // 操作缓冲区数据
    memset(mappedData, 0, 1920 * 1080 * 4); // 清除为黑色

    // 取消映射缓冲区
    gralloc->unlock(gralloc, buffer);

    // 释放缓冲区
    gralloc->free(gralloc, buffer);
}

Android 11 及后续版本的变化

  1. Allocator 3.x 和 Mapper 4.x
    • 新版本通过 AIDL/HIDL 提供更统一的分配和管理接口。
    • 增强了跨设备的兼容性。
  2. GPU 缓存一致性优化
    • 增加支持 CPU/GPU 混合访问场景的优化,减少同步开销。

相关资料

相关推荐
jiet_h25 分钟前
深入解析Kapt —— Kotlin Annotation Processing Tool 技术博客
android·开发语言·kotlin
alexhilton1 小时前
实战:探索Jetpack Compose中的SearchBar
android·kotlin·android jetpack
uhakadotcom2 小时前
EventBus:简化组件间通信的利器
android·java·github
笑鸿的学习笔记3 小时前
ROS2笔记之服务通信和基于参数的服务通信区别
android·笔记·microsoft
8931519604 小时前
Android开发融云获取多个会话的总未读数
android·android开发·android教程·融云获取多个会话的总未读数·融云未读数
zjw_swun4 小时前
实现了一个uiautomator玩玩
android
pengyu4 小时前
系统化掌握Dart网络编程之Dio(二):责任链模式篇
android·flutter·dart
水w4 小时前
【Android Studio】如何卸载干净(详细步骤)
android·开发语言·android studio·activity
亦是远方4 小时前
2025华为软件精英挑战赛2600w思路分享
android·java·华为
jiet_h4 小时前
深入解析KSP(Kotlin Symbol Processing):现代Android开发的新利器
android·开发语言·kotlin