关于硬件加速
一、硬件加速核心概念
硬件加速是将图形渲染中的光栅化从CPU转移到GPU执行的技术。CPU只需要生成绘制指令集(DisplayList),由GPU进行高效的并行光栅化计算,最终写入图形缓冲区提供屏幕显示。
本质:CPU负责逻辑指令,GPU负责繁重像素计算,分工协作提升效率
光栅化:可以高度抽象的概括为计算屏幕上每个像素点最终显示的ARGB值
二、硬件加速启用前后的核心流程对比
- 未启用硬件加速
- measure & layout:由CPU在主线程(UI线程)执行
- Draw(关键区别):
- CPU:遍历View树,在主线程直接执行每个View的onDraw(Canvas)方法
- 光栅化:onDraw中的绘制指令也由CPU执行,直接计算出最终的像素值。
- 缓冲区(Frame Buffer)
- 系统维护一个帧缓冲区。
- CPU光栅化好的像素数据直接写入这个帧缓冲区
- 核心:CPU既处理逻辑计算又处理生成最终像素的繁重计算(光栅化),然后把结果放进帧缓冲
- 合成 & 显示:屏幕读取帧缓冲区的内容显示到屏幕上。这个过程通常涉及双缓冲和Vsync信号来避免撕裂,但其绘制核心是CPU
- Front Buffer是屏幕当前帧显示的内容,Back Buffer是屏幕下一帧要显示的内容
- 开启硬件加速
- Measure & Layout:仍然由CPU在主线程执行。
- Draw(关键区别):
- CPU:遍历View树,在主线程执行每个View的**
onDraw(Canvas)
**方法。但是这里的Canvas
行为不同了 - Display List:onDraw(Canvas)中的绘制指令不再立即光栅化,而是被记录到DisplayList的数据结构中。DisplayList本质是一系列GPU能理解的绘图操作指令的序列化表示
- 光栅化:由GPU执行,CPU将构建好的
DisplayList
提交给GPU。GPU驱动程序将这些高级绘图指令并行地、高效地光栅化。
- CPU:遍历View树,在主线程执行每个View的**
- 缓冲区(Frame Buffer / GRALLOC Buffers):
- 普通开启硬件加速时的缓冲区: GPU 将光栅化好的像素数据写入系统分配的图形缓冲区 (通常是通过
Gralloc
分配管理的 Buffer Queue 中的缓冲区,如SurfaceTexture
)。这些缓冲区就是屏幕最终合成时使用的像素数据源 - 核心:CPU负责记录绘制命令(onDraw -> DisplayList);GPU负责光栅化,结果写入图形缓冲区
- Frame Buffer是抽象的缓冲区,而GRALLOC Buffers是物理缓冲区
- 普通开启硬件加速时的缓冲区: GPU 将光栅化好的像素数据写入系统分配的图形缓冲区 (通常是通过
三、启用硬件层
- 目的:对像素不会频繁变化的View采用空间换时间的方案,避免View内容未变时重复光栅化,用于后续快速合成
- 作用:仅当视图内容改变(
invalidate()
)时或主动更新时:GPU重新光栅化该View的DisplayList -> 更新离屏纹理。而只涉及纹理的变换时,不会重新光栅化DisplayList,而是直接使用纹理缓存进行合成,纹理变换正是GPU擅长的。纹理变换和opengl管线工作流程中的顶点变换是不同的层级概念 - 最佳实践
- 适合小面积静态视图或属性动画
- 避免对大视图(如列表视图)启用,易耗尽显存