Android SurfaceFlinger 颜色格式分析
更新日期:
其实是前段时间移植 2.3 的 blur 效果到 4.2 上,然后记录下一些需要注意点的地方。改的地方是 surfacefliner(代码在 framework/native/services/surfaceflinger 下面,2.3 的是在 framework/base/services/surfaceflinger 下)。这里主要说下颜色格式的问题(2.3 的 blur 效果是拿软件做的)。
大小端问题
这个过了一段时间之后老是忘记,这里要记录一下:大、小端可以理解为,高地址存储的是高位数据还是低位数据。大端存储是高地址存储是高位数据,小端存储是高地址存储的是低位数据(还有一个更取巧的记法:大端存储不要转化,和内存顺序是一致的,小端存储正好反过来)。图文讲解可以看 wiki ,很详细: Endianness
颜色格式
2.3 的 blur 效果,是通过从 GL 的 buffer 中读出 pixel 数据(glReadPixels,相当于截图),然后对这些数据进行软件的模糊算法(类高斯模糊,速度比较快),然后再把模糊后的 pixel 数据生成 texure,再贴回到 GL 上去。
所以这里就涉及到 surface flinger 的 pixel format 以及 GL 中的 pixel format。这里先说下 GL 中的 pixel format。glReadPixels 表示格式的有2个参数:一个是 format,一个是 type。这2个参数的类型可以去查红宝书的第8章, android 的代码里用的 format 和 type 就2种:
|
|
代码里面去取 OES 所使用的 format 和 type,如果 format 不是 GL_RGB 或者 type 不是 GL_UNSIGNED_SHORT_5_6_5
就强制设置为 GL_RGBA
和 GL_UNSIGNED_BYTE
,顺带可以看到把 surface 的颜色格式设置为 GGL_PIXEL_FORMAT_RGBX_8888
了(默认是 GGL_PIXEL_FORMAT_RGB_565
)。
GL format GL_RGB
就是 RGB 3通道颜色格式, GL_RGBA
就是 RGBA 4通道颜色格式。而 type 就是存储格式, GL_UNSIGNED_SHORT_5_6_5
是打包的存储方式(GL 中这种 5_6_5
, 4_4_4_4
之类的都是打包的存储方式)。所谓打包的存储方式,就是把前面的 RGB 3通道数据打包到 16 位的无符号整数中。特别注意一点,GL 的打包数据的存储格式总是将颜色分量的高位打包到高位,和 host 的存储方式无关。就是说 GL_UNSIGNED_SHORT_5_6_5
with GL_RGB
就是 R(16,11)—G(11,5)—B(5,0) 的存储顺序。但是不打包的存储格式(例如 GL_UNSIGNED_BYTE
),就是和存储格式相关的。看看代码的转化:
|
|
可以看的 android 只会转化 GGL_PIXEL_FORMAT_RGBX_8888
格式的, GGL_PIXEL_FORMAT_RGB_565
的不需要转化(因为前面说了 GL 打包的格式是固定是小端存储的)。
然后再看下 android surface 的颜色格式定义。surface 用的颜色格式定义在 pixelflinger 中。这个 pixelflinger 是 android 自带的 GL 软件实现,现在一般机器上的都不用这个了,但是颜色格式定义还是用这个的(代码在 system/core/libpixelflinger/)。
|
|
从上面的定义可以看得到 GGL_PIXEL_FORMAT_RGBX_8888
是 ABGR 的小端存储格式,所以上面如果 host 是小端格式,就不用转化,是大端的话就需要转化一下。这里的 RGBA 定义感觉挺奇怪的,和 java 层的 Bitmap ARGB 的定义顺序不一样,不知道为什么要这么定义。
GGL_PIXEL_FORMAT_RGB_565
正好和 GL_UNSIGNED_SHORT_5_6_5
with GL_RGB
存储顺序是一样的,所以 5_6_5
的颜色格式也不需要转化。
颜色格式搞清楚了,软件算法用现成的就好啦。android 2.3 的 blur 效果不算很好,但是速度很快,网上有很多软件的 blur 算法,效果比 2.3 的好,但是速度慢不少。高斯模糊好像就是对这些像素点搞个啥加权求均值,具体的以后再研究了,这次只是把颜色格式搞清楚。
哎,这样吐槽下,以前移植、改的 blur 软件算法的 32位格式 RGBX_8888
格式是错的,只不过一般机器上的 OES 都是 565 的,所以没暴露出来而已,呵呵,以后有空在改吧。