Android硬件加速

原文地址http://developer.android.com/guide/topics/graphics/hardware-accel.html


硬件加速
Android 3.0 (API level 11), 开始支持
所有的View 的canvas都会使用GPU,但是硬件的加速会占有一定的RAM。
在API >= 14上,默认是开启的,如果你的应用只是标准的View和Drawable,全局都打开硬件加速,是不会有任何问题的。
然而,硬件加速并不支持所有的2D画图的操作,这时开着它,可能会影响到你的自定义控件或者绘画,出现异常等行为,
所以android对于硬件加速提供了可选性

如果你的应用执行了自定义的绘画,可以通过在真机上测试开启硬件加速查找问题


硬件加速的级别

Application  <application android:hardwareAccelerated="true" ...>

Activity
<application android:hardwareAccelerated="true">
<activity ... />
<activity android:hardwareAccelerated="false" />
</application>

Window
getWindow().setFlags(
   WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
   WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);

View
myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);

Note: 你可以关闭View级别的硬件加速,但是你不能在View级别开启硬件加速,因为它还依赖其他的设置


两种获取是否支持硬件加速的方式
View.isHardwareAccelerated() returns true if the View is attached to a hardware accelerated window.
Canvas.isHardwareAccelerated() returns true if the Canvas is hardware accelerated
如果必须进行这样的验证,建议你在draw的代码块中使用:Canvas.isHardwareAccelerated(),因为如果一个View被attach到一个硬件加速的Window上,
即使没有硬件加速的Canvas,它也是可以被绘制的。比如:将一个View以bitmap的形式进行缓存

Android的绘制模型
开启硬件加速后,Android框架将采用新的绘制模型。
基于软件的绘制模型和基于硬件的绘制模型的区别:

  应用程序调用invalidate()更新UI的某一部分,失效(invalidation)消息将会在整个视图层中传递,计算每个需要重绘的区域(即脏区域)。
  然后Android系统将会重绘所有和脏区域有交集的view。很明显,这种绘图模式存在缺点:

1. 每个绘制操作中会执行不必要的代码。比如如果应用程序调用invalidate()重绘button,而button又位于另一个view之上,
    即使该view没有变化,也会进行重绘。

2. 可能会掩盖一些应用程序的bug。因为android系统会重绘与脏区域有交集的view,所以view的内容可能会在没有调用invalidate()的情况
    下重绘。这可能会导致一个view只有在其它view时失效才得到正确的行为。这种行为可能在每次修改应用的时候都会发生改变。
    因此,你需要一直调用invalidate在你的自定义控件上,不管那些涉及到重绘的代码是否修改了数据或状态。

Note:android view 在属性值变化的时候会自动调用invalidate,比如一个TextView的颜色或者背景的变化。

Android系统仍然使用invalidate()和draw()来绘制view,但在处理绘制上有所不同。
Android系统记录绘制命令到显示列表,包含的视图层次的绘图输出,而不是立即执行绘制命令。
另一个优化就是Android系统只需记录和更新标记为脏(通过invalidate())的view。新的绘制模型包含三个步骤:

1. Invalidate the hierarchy
2. 记录和更新显示列表
3. 绘制显示列表

 在这种模式下,你不能指望一个视图相交的肮脏的地区会执行其draw()方法。为了确保Android系统记录视图的显示列表,你必须调用
 invalidate()。否则会导致View不会刷新。
 使用显示列表对动画的性能也会有好处,因为某些明确的属性,例如 alpha或者旋转,不要求invalidate目标View,(会自发的执行)。
 这种优化也可以应用于所有显示列表的视图(当application硬件加速的时候)。
 
 假设有一个LinearLayout,包含上述按钮列表。对于LinearLayout显示列表看起来像这样:
DrawDisplayList(ListView)
DrawDisplayList(Button)

 假设你想改变ListView的透明度,在listview上调用了setAlpha之后,这个显示列表包括:
SaveLayerAlpha(0.5)
DrawDisplayList(ListView)
Restore
DrawDisplayList(Button)

ListView的复杂的draw代码块没有执行,相反,系统只会更新这个更简化的显示列表,如果应用中没有开启硬件加速,list和其父类的draw代码块
会再次执行。

硬件加速的2D渲染管道的建立是第一个支持不成比例的绘画,但是过高的值会影响到绘图操作的质量。
这些绘制的操作是按照1.0的规模纹理实现的,由GPU转化。在API级别<17,伴随着规模的增长会导致

如果你的应用程序是由任何这些特征缺失或限制的影响,你可以通过setLayerType(View.LAYER_TYPE_SOFTWARE, null).关闭它,不会影响到你再
别的地方使用硬件加速。

在所有版本的Android,所有的View具有渲染到锁屏缓冲区的能力,或通过View的绘制缓存,或者调用 Canvas.saveLayer(). 
锁屏缓冲区或者layers拥有几种用途。在实现复杂的动画或者应用于组件效果器的时候。比如, 实现退色效果:通过Canvas.saveLayer 临时的分发一个view到layer,
然后以一个不透明的参数返回.

在Android 3(API级别11开始),你有更多的控制如何以及何时使用层与视图setlayertype()方法。
这个API有两个参数:Layer的类型和一个可选的Paint,你可以使用Paint参数应用到颜色过滤器,特殊的混合模式,或者对于一个图层的不透明度。

视图可以使用三个layer类型:

LAYER_TYPE_NONE:
正常的使用,不会通过锁屏的缓冲区返回。

LAYER_TYPE_HARDWARE:
视图是由硬件实现为硬件机构如果应用硬件加速。如果应用程序没有硬件加速,这层型表现相同layer_type_software。

LAYER_TYPE_SOFTWARE: 


layer的类型依赖于你的需求;

性能
使用硬件层类型来渲染一个视图到纹理层,一旦视图被渲染成一层,其绘图代码不必执行,直到视图调用invalidate()执行。
一些动画,如α-动画,然后可以被直接应用到层,使用GPU来做是非常高效的。

视觉效应:
使用硬件或软件层型和涂料适用于特殊的视觉处理的观点。例如,你可以通过colormatrixcolorfilter画一个黑白相间的视图。

兼容性:
使用一个软件层类型去强制渲染一个视图。如果一个被硬件加速的视图(例如,如果你的整个应用程序的硬件加速),就会出现
渲染的问题,这是一个解决硬件渲染管线限制的简单的方法。

当你的应用程序的硬件加速,硬件层可以提供更快和更平滑的动画。
在每秒60帧运行一个处理大量绘图操作的复杂动画有时候是不可能的。
这可以通过使用硬件层渲染为硬件纹理缓解。然后硬件纹理可以用来制作视图的动画,不需要视图在动画的时候不断重绘自己。视图不被重绘,
除非你改变视图的属性,调用了invalidate(),或者你手动的调用invalidate,你将不会得到一个平滑的动画。这时你需要考虑开启硬件层应用
到你的动画。

当一个视图是由硬件层的支持,它的一些属性通过layer被合成到屏幕的方式处理。
设置这些属性将是有效的因为他们不需要视图invalidate和重绘。下面列出的属性影响layer合成的方式

alpha: 
Changes the layer's opacity

x, y, translationX, translationY: 
Changes the layer's position

scaleX, scaleY: 
Changes the layer's size

rotation, rotationX, rotationY: 
Changes the layer's orientation in 3D space

pivotX, pivotY: 
Changes the layer's transformations origin

因为硬件层使用视频内存,它是高度推荐你在启动动画的时候开启它们,在动画完成的时候关闭它们。


Tip & Tricks
切换硬件加速的2D图形可以立即提高性能,但你仍应该遵循以下建议以便有效地利用GPU应用程序

减少应用程序中的View的数量
需要绘制的视图越多,它的速度就越慢。这同样适用于软件渲染。减少视图是一个简单的方法来优化您的UI。

避免透支
不在彼此的顶部画太多的层次。移除任何被它上面不透明的视图完全遮盖的视图。如果你需要绘制几层的混合在一起,把它们合并为一个单一的层。
对于当前的硬件,一个好的经验法则是不在屏幕上画出每帧的像素数超过2.5次(在一个位图透明像素计数!)。

不要创建渲染对象的绘制方法
一个常见的错误是,每一次渲染方法被调用的时候都创建一个新的Paint或一个新的Path。这迫使垃圾收集器运行更加频繁,也绕过缓存优化的硬件管道。

不要太频繁的修改形状
复杂的形状,Path,Circle,每次都是通过texture masks来渲染的,每次创建或者修改Path,这个硬件管道会创建一个新的mask,而这时十分昂贵的。

不要太频繁的修改Bitmap
每次改变Bitmap的内容,都会作为一个GPU texture再次上传,然后下次重新绘制。

谨慎使用alpha

当你使用setAlpha,AlphaAnimation或者ObjectAnimator实现一个透明的View时,它会在一个双倍的填充率的离屏的缓冲区渲染。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值