3

Android硬件加速

 3 years ago
source link: https://blog.csdn.net/eclipsexys/article/details/44228403
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Android硬件加速_eclipse_xu-CSDN博客_android 开启硬件加速

从Android 3.0开始(API L11),Android开始全面使用硬件加速来进行2D渲染,硬件加速是指Android中在View上进行绘制的图形图像都使用GPU来进行绘制,使用硬件加速,在大部分时候都让绘制更加流畅,但付出的代价是需要消耗更多的内存资源。

硬件加速在API L14之上是默认开启的,对于基本的View绘制,通过硬件加速可以增加绘图的流程性,但是要注意的是,并不是所有的2D图形绘制API都支持硬件加速。

通过开发者选项中的“强制进行GPU渲染”,用户可以为全局打开硬件加速。在3.0 以上的Android中,系统已经对大部分动画都进行了硬件加速。

  • GPU:Graphic Processing Unit (图形处理器)
  • OpenGL:Open Graphic Library 定义了一个跨编程语言、跨平台的编程接口的规格,不同厂商会有不同的实现方法,它主要用于三维图象(二维的亦可)绘制。
  • SurfaceFlinger:Android中负责Surface之间叠加、混合操作的动态库
  • Skia:Android中的2D图形库

控制硬件加速

由于硬件加速对某些2D绘图API的不支持,所以Android系统提供了四种级别的控制方式。

Application级别

在应用的Android清单文件中,把下列属性添加到<application>元素中,来开启整个应用程序的硬件加速,代码如下所示:

android:hardwareAccelerated="true"

Activity级别

比整个App范围稍小,我们可以在Activity范围内进行控制,代码如下所示:

android:hardwareAccelerated="true"

Window级别

针对单个的Window,Android同样可以控制硬件加速,代码如下所示:

但是对Window来说,Android无法禁止硬件加速。

View级别

View级别是用的最多的控制硬件加速的级别,我们可以通过如下所示的代码来禁止硬件加速:

setLayerType(View.LAYER_TYPE_SOFTWARE, null);

与Window级别相反,我们无法在View级别开启硬件加速。

判断View是否已开启硬件加速

判断View是否支持硬件加速一般有如下所示的两种方法:
尽量使用Canvas对象的判断方法。

Android绘图模式

相对于是否开启硬件加速模式,Android的绘图模式被分为两种——基于软件的绘图模式与基于硬件的绘图模式。

基于软件的绘图模式

基于软件的绘图模式在重绘View时,需要如下两个过程:

  • Invalidate the hierarchy
  • Draw the hierarchy
需要进行重绘时,系统发出invalidate()信号,并在View视图树中进行传递,计算需要重新绘制的区域,但是这种绘图方式有两个不足:
  1. 当我们只需要重绘视图树中的一个View时,视图树中的View都将进行重绘,而且遍历视图树也浪费大量时间。例如一个ViewA在另一个ViewB之上,即使B没有发生变化,重绘A的时候,B也会重绘。
  2. 这种方式隐藏了绘制中的bug,例如上面的例子中,由于ViewA、ViewB相互重叠,有需要重绘的the dirty region,那么如果B忘记了进行重绘的逻辑,那么A进行重绘的时候,就会将B重绘,也就是说使用错误的行为来得到了正确的现象。正是因为这个原因,开发者需要保证在View需要发生重绘时,调用正确的invalidate()方法。

基于硬件的绘图模式

基于硬件的绘图方式同样使用invalidate()信号来进行重绘,但其绘制和渲染的方式不同。Android内部维护一个display list用于记录视图树的显示状态。当收到invalidate()信号时,系统只需要更改需要重绘的视图的display list,而其他未发生改变的视图只需要使用原来的display list即可,整个过程分为三部分:
  • Invalidate the hierarchy
  • Record and update display lists
  • Draw the display lists

使用这种方式,就可以避免软件绘图中第二点的bug。

例如,假设有一个包含了一个Button对象的ListView对象的LinearLayout布局,那么LinearLayout布局的显示列表如下:

1. DrawDisplayList(ListView);

2.DrawDisplayList(Button)

假设现在要改变ListView对象的不透明度,那么在调用ListView对象的setAlpha(0.5f)方法时,显示列表就包含了以下处理:

1.SaveLayerAlpha(0.5);

2.DrawDisplayList(ListView);

3. Restore;

4.DrawDisplayList(Button)

不支持硬件加速的绘图方法

如果应用程序受到这些错误的功能或限制的影响,那么能够通过调用setLayerType(View.LAYER_TYPE_SOFTWARE, null)方法针对应用程序受到影响的部分来关闭硬件加速。

具体哪些方法不支持硬件加速可以参考Google开发者网站上的这篇文档 http://developer.android.com/guide/topics/graphics/hardware-accel.html

View Layers

在所有的Android版本中,View都可以通过Canvas.saveLayer()方法来获得离屏缓冲的能力,离屏缓冲区或层有多种用途,特别是在呈现复杂的动画或使用组合效果时,能够获得更好的性能。例如,使用Canvas.saveLayer()可以实现淡入淡出的效果,先暂时把一个View对象渲染在一个层中,然后把它和不透明因子合成到屏幕上显示。

从Android3.0(API Level 11)开始,用View.setLayerType()方法使用层的方式和时机会更多的控制。这个API需要两个参数:一个是层的类型,另一个是可选的,用于描述层应该如何被合成的Paint对象。能够使用这个Paint对象来进行颜色过滤、特殊的混合模式、或者层的透明度。View对象能够使用以下三种层类型:

  • LAYER_TYPE_NONE:View对象用普通的方式来呈现,并且不是由屏幕外缓存来返回的。这种类型是默认的行为;
  • LAYER_TYPE_HARDWARE:如果应用程序是硬件加速的,那么该View对象被呈现在硬件的一个硬件纹理中。如果没有被硬件加速,那么这种层类型的行为与LAYER_TYPE_SOFTWARE相同。
  • LAYER_TYPE_SOFTWARE:View对象会被呈现在软件的一个位图中。

使用哪种层的类型,依赖以下目标:

  • 性能:使用硬件层类型,把View呈现到一个硬件纹理中。一旦该View对象被呈现到一个层中,那么它的绘图代码直到调用该View对象的invalidate()方法时才会被执行。对于某些动画,如alpha动画,就能够直接使用该层,这么做对于GPU来说是非常高效的。
  •  视觉效果:使用硬件或软件层类型和一个Paint对象,能够把一些特殊的视觉处理应用给一个View对象。例如,使用ColorMatrixColorFilter对象绘制一个黑白相间的View对象。
  •  兼容性:使用软件层类型会强制把一个View对象呈现在软件中。如果View对象被硬件加速(例如,如果整个应用程序都被硬件加速)发生呈现问题,那么使用软件层类型来解决硬件呈现管道的限制是一个容易的方法。

View layers and animations

当应用层使用硬件加速的时候,手机显示硬件可以让动画、显示效果更加平滑。如果你的动画效果不够流畅,那么就需要考虑在View层面上使用硬件加速来进行优化。在Android中,有些视图操作使用硬件加速是非常高效的,因为这些操作不需要让对象失效后重绘,例如:

1. alpha:改变层的透明度

2. x,y,translation,translation:改变层的位置

3. scaleX,scaleY:改变成的缩放

4. rotation,rotation,rotationY:改变3D空间中视图的方向

5. pivotX,pivotY:改变层的变换控制点

对于以上属性的动画,在开启硬件加速后将会得到非常高效的绘制,下面的代码展示了如何高效的在3D空间中围绕Y轴旋转View对象,代码如下所示:

但是由于硬件加速会消耗系统内存,因此强烈建议在动画结束后取消硬件加速,代码如下所示:

硬件加速的缺点

当我们使用硬件加速时,会消耗更多的内存(将近4倍),如果分给应用的内存没有这么多,那么就会从系统剩于内存中进行划分,因此,硬件加速不适用于系统的核心进程。好的应用,应该在硬件加速(GPU)与软件绘制(CPU)中找到平衡点。

        另外,需要注意的是,App中进行UI渲染是无法使用并发的,多核心无法带来显示上的性能提升。同时,分辨率也是影响流畅度的一个非常重要的方面,为了能够在更高的分辨率上进行流畅的绘制效果,那么就需要使用更加强大的GPU进行渲染。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK