硬件加速(HardwareAccelerated)

来源:互联网 发布:易语言编程 编辑:程序博客网 时间:2024/06/04 19:16

从Android3.0(API Level 11)开始,Android 2D渲染管道能够更好的支持硬件加速

。硬件加速执行的所有的绘图操作都是使用GPU在View对象的画布上来进行的。因为启用硬件加速会增加资源的需求,因此这样的应用会占用更多的内存。  启用硬件加速的最容易的方法是给整个应用程序都打开全局硬件加速功能。如果应用程序只使用标准的View和Drawable,那么打开全局硬件加速不会导致任何的不良的绘制效果。但是,因为硬件加速并不支持所有的2D图形绘制操作,所以对于那些使用定制的View和绘制调用的应用程序来说,打开全局硬件加速,可以会影响绘制效果。问题通常会出现在对那些不可见的元素进行了异常或错误的像素渲染。为了避免这种问题,Android提供以下级别,以便可选择性的启用或禁止硬件加速:

1. Application 2. Activity 3. Window 4.View  如果应用程序执行了定制化的绘图,就要在实际的带有硬件加速的硬件设备上测试,以便发现问题。   控制硬件加速  能够用以下级别来控制硬件加速 Application级别  在应用的Android清单文件中,把下列属性添加到<application>元素中,来开启整个应用程序的硬件加速。

 <applicationandroid:hardwareAccelerated="true" ...>

Activity级别  如果应用程序不能够正确的使用被打开的全局硬件加速,那么也可以对Activity分别进行控制。在<activity>元素中使用android:hardwareAccelerated属性,能够启用或禁止Activity级别的硬件加速。以下示例启用全局的硬件加速,但却禁止了一个Activity的硬件加速:

 <applicationandroid:hardwareAccelerated="true">   

 <activity ... />     

<activityandroid:hardwareAccelerated="false" />

</application>

 Window级别 

如果需要更细粒度的控制,就可以使用下列代码来针对给定的窗口来启用硬件加速: getWindow().setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,    WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED); 注意:当前不能在Window级别禁止硬件加速。 View级别 能够使用下列代码在运行时针对一个独立的View对象来禁止硬件加速:myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);  注意:当前不能在View级别开启硬件加速。View层除了禁止硬件加速以外,还有其他的功能,更多的相关信息请看本文的“View层”。 判断一个View对象是否被硬件加速  有些时候,尤其是对于那些定制的View对象,应用程序知道当前的View对象是否被硬件加速是十分有益的。如果应用程序做了很多定制的绘图操作,并且不是所有的操作都会被新的渲染管道所支持,那么这种判断就特别有用。  有两种不同的方法来检查应用程序是否被硬件加速了:

 1. 如果一个View对象跟一个被硬件加速的窗口绑定,那么View.isHardwareAccelerated()方法就会返回true;

 2. 如果一个Canvas对象被硬件加速了,那么Canvas.isHardwareAccelerated()方法就会返回 true。 

如果必须要在绘图代码中做这种检查,那么在可能的情况下,要使用Canvas.isHardwareAccelerated()方法来代替View.isHardwareAccelerated()方法。当一个View对象跟一个被硬件加速的窗口绑定的时候,它依然能够使用使用一个非硬件加速的Canvas对象。例如,把一个View对象绘制到缓存中的一个位图时就会发生这种情况。 Android的绘图模式  当硬件加速被启用时,Android框架会采用一个新的绘图模式,这种模式利用显示列表把应用程序呈现在屏幕上。要充分理解显示列表,以及它们是如何影响应用程序的,对于理解Android是如何绘制没有硬件加速的View对象是有益的。下面分别介绍基于软件的和硬件加速的绘图模式。 基于软件的绘图模式  在软件的绘图模式中,View对象是通过以下两个步骤来绘制的:

1. 让View层次结构失效;

2. 绘制View层次结构。  无论何时,应用程序需要更新它的UI部分时,都回调用发生内容改变的View对象的invalidate()方法。无效的消息请求会在View对象层次结构中传递,以便计算出需要重绘的屏幕区域(脏区)。然后,Android系统会在View层次结构中绘制所有的跟脏区相交的区域。

不幸的是,这种方法有两个缺点:

 1. 这种模式在每个绘图传递中需要很多的代码执行。例如,如果应用程序调用了一个按钮 的invalidate()方法,并且该按钮位于另一个View对象的上方,那么即使该View对象没有变化,那么Android系统也要重新绘制它。 

2. 第二个问题是这个种绘图模式能够隐藏应用程序中的bug。因为当View对象跟脏区相 交时,Android系统就会重新绘制它,所以即使没有调用View对象上的invalidate()方法,那么View对象内容的改变也可能会导致它被重绘。当发生这种情况时,就要依赖另一个被失效的View对象来获取正确的行为。这种行为能够改变每次你对应用程序的修改。因为这个原因,在修改影响View对象的绘图代码的数据和状态是,应该始终调用该定制View对象的invalidate()方法。 

注意:在View对象的属性发生变化时,如背景色或TextView对象中的文本等,Android系统会自动的调用该View对象的invalidate()方法。 硬件加速绘图模式  这种模式下,Android系统依然会使用invalidate()方法和draw()方法来请求屏幕更新和展现View对象,但是实际的绘图处理是不同的,它会立即执行绘图命令,Android系统把这些命令记录在内部的显示列表中,列表中包含了View对象层次结构的绘图代码的输出。另一种优化是:Android系统只需要针对由invalidate()方法调用所标记的View对象的脏区进行记录和更新显示列表。没有失效的View对象能够通过重新发布先前被记录的显示列表来进行简单的重绘工作。这种绘图模式包含三个阶段:

1. 让View的层次结构失效;

 2. 记录和更新显示列表;

3. 绘制显示列表。

使用这种模式,不能够依赖相交的脏区View的draw()方法来执行绘图工作。要确保Android系统记录一个View对象的显示列表,就必须调用invalidate()方法,如果忘记调用该方法,那么在变化发生后,View对象看上去会跟变化之前相同,这是一个比较容易发现的Bug。 使用显示列表对提升动画的性能也是有好处的,因为设置诸如透明度、旋转等属性时,不需要让目标View对象失效(系统会自动做这件事)。这种优化还适用于带有显示列表的View对象(应用程序被硬件加速时的任意View对象)。

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

1.      DrawDisplayList(ListView); 2.DrawDisplayList(Button)。

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

3.       1. SaveLayerAlpha(0.5);  2. DrawDisplayList(ListView); 3. Restore; 4. DrawDisplayList(Button).  这里没有执行复杂的ListView对象的绘图代码。相反,系统只是比较简单的更新了LinearLayout对象的显示列表。在一个没有启用硬件加速的应用程序中,该列表(ListView)和它的父对象都会再次执行绘图代码。 不被硬件加速所支持的绘图操作  在硬件加速的时候,2D渲染管道支持大多数的通常用于Canvas的绘图操作,以及一些很少使用的操作。被用于渲染应用程序的所有的绘图操作都有发送给Android系统,默认的Widget和布局,以及一些常用的可视效果,如反射和瓷砖的纹理效果都是被支持的。以下列出了已知的不支持硬件加速的操作:

4.      1. Canvas  chipPath() chipRegion() drawPicture()drawPosText() drawTextOnPath() drawVertives()

5.      2. Paint  setLinearText() setMaskFilter()setRasterizer()  另外,还有一些操作行为会因启用了硬件加速而不同:

6.       1. Canvas clipRect():硬件加速会忽略XOR、Difference和ReverseDifference三种剪辑模式,3D变换不适用于剪辑矩形。  drawBitmapMesh():硬件加速会忽略颜色数组。 drawLines():硬件加速不支持抗锯齿处理。  setDrawFilter():硬件加速能够被设置,但是会被忽略。

7.       2. Paint setDither():硬件加速会忽略其设置。  setFilterBitmap():位图过滤是始终打开的。

0 0
原创粉丝点击