这是一个非常经典的问题,使用错误的 gralloc usage flag 会直接影响 buffer 的分配方式和内存访问路径,从而造成严重的性能问题,甚至掉帧。
我们来一步步解释这个问题:
1. 什么是 gralloc usage flag?
Gralloc(Graphics Allocation)是 Android HAL 中用于 GPU/Camera/Display/Codec 等模块分配图形 buffer 的服务。
这些 buffer 的用途千差万别,所以需要使用一组标志(usage flags)告诉 gralloc:
-
谁会访问这个 buffer(CPU 还是 GPU 还是硬件 codec)?
-
怎么访问(读?写?频繁?偶尔?)?
-
是否需要物理连续内存?是否用于 DMA?
2. 如果使用了错误的 flag 会发生什么?
情况一:flag 表示“CPU 只读”,但其实你还要写
-
gralloc 可能分配一个只读映射的内存(mmap 只映射成读)
-
当你尝试写入,就可能出错或性能极差(页保护、异常、TLB flush)
情况二:你没有加 SW_*,但你用 CPU 访问
-
gralloc 会以为你不需要 CPU 访问,可能根本不会分配可映射的 buffer
-
所以你访问 buffer 时要么失败,要么触发昂贵的 cache flush / sync
情况三:你没有加 HW_VIDEO_ENCODER,但其实是送给 codec 的
-
gralloc 不知道这是 encoder 用途,可能没走 IOMMU、没走连续内存
-
导致 encoder 无法直接 DMA,增加 memcpy 或 map copy 的开销
-
高并发时很容易掉帧,尤其是视频录制(要求 steady 30fps 或 60fps)
3. 问题总结(掉帧原因)
缺少正确的
usage flags→ gralloc 分配不合适的 buffer → 导致访问失败或访问慢 → 导致某些阶段等待过久 → pipeline 堵塞 → 帧被 drop
4. 正确做法
根据你的 buffer 用途添加合适的 flag,比如:
-
CPU 要频繁读写 →
GRALLOC1_PRODUCER_USAGE_CPU_READ_OFTEN+GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN -
encoder 读 buffer →
GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER -
GPU 用 →
GRALLOC1_CONSUMER_USAGE_GPU_TEXTURE(GL)或HWCOMPOSER -
camera output →
GRALLOC1_CONSUMER_USAGE_CAMERA
5. 为什么用了正确 flag 就不卡了?
因为 gralloc 会根据 flag 做:
-
更合适的 buffer 类型选择(ION heap 类型、contiguous or not)
-
合适的 cache 策略(cached or uncached)
-
更优的 DMA 或物理地址映射
-
避免多余的 memcpy / sync,减少延迟,确保 pipeline 平稳运行

被折叠的 条评论
为什么被折叠?



