Android Hardware Acceleration研究未遂

来源:互联网 发布:php 反射函数参数类型 编辑:程序博客网 时间:2024/04/30 06:48

大概两年前,我在Android开发者网站上读过关于硬件加速(Hardware Acceleration)的介绍,当时是不明觉厉,隐约记得有个概念是display list,即屏幕上的输出是由多个display list依次绘制上去的,主要的作用是通过GPU硬件来做scale渲染(unscaled drawing),以此来保证适配高分辨率时的渲染质量和效率。

 最近再次拜读这篇developer guide,发现虽然标题还是叫Hardware Acceleration,但是内容变化很多,记忆中的display list概念还在,但并未做深入介绍,不似之前印象中的图文讲解了,而Hardware Acceleration的目的已经不是最初的保证在高分辨率渲染时的质量和效率了(虽然在guide中仍保留有一小段提及),而是全方位地提升UI渲染的性能,尤其是Andorid动画的性能。

Hardware Acceleration引入于Android 3.0 (API Level 11),从ICS(API Level 14)开始,应用程序的Target API Level如果高于14(包含),则硬件加速便是默认打开的。即便是这样,谷歌仍然承认,在有些场景下,例如开发者使用了自定义的View组件,开启硬件加速可能会带来意外的效果(不可见、抛异常、像素错乱等)。所以谷歌提供了各种级别的硬件加速的开关,包括Application、Activity和View级别,详细可以参考developer guide(http://developer.android.com/guide/topics/graphics/hardware-accel.html#controlling)。


文章通过对比以前采用的软件渲染(Software-based Drawing Model)和硬件加速渲染(Hardware Accelerated Drawing Model)模型来说明硬件加速的高大上,现搬运如下:

Software-based Drawing Model流程:

  1. Invalidate the hierarchy
  2. Draw the hierarchy

重绘的出发点是invalidate View对象(显式调用invalidate方法或修改View属性),然后计算dirty area,然后将View所在的Hierarchy中所有和dirty area有交集的View都重新绘制一次。明显的缺点就是会引起不需要重绘的View组件调用自己的重绘代码,增加渲染负载。


Hardware Accelerated Drawing Model流程

  1. Invalidate the hierarchy
  2. Record and update display lists
  3. Draw the display lists

此模型中引入了display list的概念,被invalidate的View组件不会立刻重绘,而是被记录进display list并将其更新,然后将所有display lists绘制到屏幕。只有被invalidate的View所在的display list会被更新,没有被invalidate的View就直接复用其display list而不需要重新执行绘制代码,这样就将重绘的影响限制在了display list内部。启用了硬件加速的应用在播放动画时性能会大大提升,动画指令(如alpha,scale等)操作在display list上,而不需要重新绘制View组件。具体流程解释可以参考原文(http://developer.android.com/guide/topics/graphics/hardware-accel.html#hardware-model)。

尽管硬件加速霸气微漏,目前仍然有许多的绘制操作(即Canvas对象的某些方法)是不被硬件加速支持的,也就是说,如果你的应用某个模块或者某个View使用了不被支持的绘制操作,那么你最好关掉硬件加速。不被硬件加速支持的绘制操作列表也被热心的谷歌整理出来便于开发者查阅(http://developer.android.com/guide/topics/graphics/hardware-accel.html#unsupported)


这便是Android开发者网站上对于Hardware Acceleration的解释了。开发者要做的很简单:能开启硬件加速就开启,如果发现有些View显示有bug,参考不支持的列表,就关掉硬件加速。作为一篇Guide,这篇文章已经合格了。不过其对于硬件加速的原理没有涉及,而display list机制的解释也太过春秋笔法,本来奔着Android Render Pipeline去看的,看完后发现完全提取不到吹牛的素材啊!

于是乎在网上寻觅到了一些网友的讨论和谷歌里Android工程师的分享,搬运过来分享给各位。

How about some Android graphics true facts?

作者是谷歌内部Android Framework工程师Dianne Hackborn(这名字不搞IT确实委屈),写的较早(2011年底)据作者讲,写这篇文章的初衷是网上太多关于Hardware Acceleration的以讹传讹(官方的介绍如此含糊,能没有传言吗),需要一篇文章以正视听,结果写下这篇文章后引起了更多的回复和讨论。。。所以这篇文章的节奏整体还是挺欢乐的。我从这篇文章中,也提取到了一些硬件加速的机制原理:

1. 硬件加速的实现方式是用OpenGL来渲染2D图形,开启硬件加速的应用在运行时,会分配大概8M的内存给OpenGL,也就是这是个空间换时间的博弈。如果应用程序对内存造成了较大压力,可以尝试关掉硬件加速试试。

2. Android从1.0开始就有硬件加速渲染,但是是window级别的,屏幕上各个window(例如Status Bar, Launcher, 当前应用窗口等)的渲染(例如应用弹出,下拉Status Bar等)就是由硬件来完成的。而在3.0以前,Window内部的渲染确实是用软件来实现的,这点可以对应到Develop Guide中的“Software-based Drawing Model”。根据Hackborn的说法,现在developer guide上的Hardware Acceleration是指Window内部的渲染机制而言的。

3. 那么window和display list的关系应该是这样:一个window中可以包含多个display list。一般来说一个Activity对应一个window,而View和display list之间的对应关系目前还不清楚。

4. 在没有硬件加速的时代,渲染效率完全取决于屏幕上的像素个数以及CPU的性能,如果像素数够少,渣一些的CPU依然能够流畅跑起60fps,相反如果像素数很多,而CPU没有跟上分辨率提升的步伐,渲染效率就会变差。硬件加速可以打破这两个因素的制约,其通过scale来实现高分辨率的渲染,而且可以保证在scale时尽量不损失质量(或许采用mipmap纹理?),这一点也呼应了developer guide上提过的硬件加速的初衷。

5. 硬件加速当真不是万金油,该关就关。

其实我感觉其实谷歌想把硬件加速做成一个对开发者透明的东西,后来发现实在是瞒不住,于是暴露了不同层次的开关给开发者调用。森森觉得谷歌在“butter smooth UI”这条路上被开发者和竞争对手苹果逼的夺路狂奔啊。

How do the pieces of Android's (2D) Canvas drawing pipeline fit together?

这是SO上关于Andorid 2D渲染通道的讨论,该帖楼主苦寻无果,便发奋图强研究源码自己总结出了一套机制(见帖子回复链接),Romain Guy也回复了该帖子,我偷懒没细看。

Android 4.4 & rendering pipeline improvements

作者为喜闻乐见的谷歌Android工程师Romain Guy,这哥们介绍了下4.4中渲染通道的新特性。感兴趣可以细读下。

Android Graphics

谷歌的一篇介绍Android Graphics的文档。


这篇文章东拼西凑,写的也很乱。一开始想把Hardware Acceleration搞明白,结果发现的问题多于答案,很多概念和机制依然比较混乱,期待以后能够将其梳理的更为透彻。不过聊以此文整理沉淀下目前的知识,留作以后继续研究的存档。请各位看官尽情指出纰漏,欢迎分享更纯粹的见解!



0 0
原创粉丝点击