Android中GPU硬件加速控制及其在2D图形绘制上的局限

图形的渲染可分为两种:软件渲染和硬件渲染。软件渲染是靠CPU计算各种坐标并绘制,主要是占用内存;硬件渲染是靠GPU,主要占用显存,一般的3D图形程序(OpenGL、DirectX)都是GPU加速的。

在Android3.0之前,2D绘图API只支持软件渲染模式,从Android3.0开始,2D绘图API开始支持GPU硬件渲染,即View中的Canvas的绘图操作会使用GPU,所以从Android 3.0(API Level 11)开始,View中就多了一些和硬件相关的方法。如果App的AndroidManifest.xml文件中定义的 targetSdkVersion大于或等于14(Android 4.0),那么Android会默认为App启用GPU渲染2D图形,我们也可以自己决定是否使用GPU,见下文。如果开启了GPU硬件加速,那么Android会用OpengGL绘图中常见的Display List技术对OpenGL ES中的绘图命令进行缓存,提高绘图效率与速度。关于Android中GPU硬件加速的Display List绘图机制会在以后专门写文章进行阐述,本文不做过多介绍。


控制是否使用GPU

我们也可以显式地启用或禁用GPU渲染,并且可以从多个Application、Activity、Window、View多个级别对其进行控制。

  • Application

    在AndroidMenifest.xml的中添加如下的属性即可在整个App的所有Activity的View中启用GPU硬件加速渲染2D图形:

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

  • Activity

    你既可以在Application级别上控制GPU是否启用,也可以在Activity级别对其就进行控制。比如你的App中有多个Activity,你想让大部分Activity启用GPU硬件加速,但有一个Activity你不想启用硬件加速,你可以通过以下的配置实现:

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

    如果你想要更加细粒度地对GPU的使用进行控制,你可以通过代码对指定的Window启用GPU硬件加速,如下代码所示:

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

    需要注意的是在运行时不能通过代码禁用掉某个Window的硬件加速。

  • View

    你也可以在运行时通过如下代码为某个指定的View禁用掉GPU硬件加速:

    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB){
        //View从API Level 11才加入setLayerType方法
        myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
    }

    View从API Level 11才加入setLayerType方法,所以在使用前需要判断一下当前系统运行的版本。 需要注意的是,在运行时不能通过代码为某个View启用GPU硬件加速。


判断当前是否处于硬件加速中

从Android 3.0(API Level 11)开始,View和Canvas类都加入了isHardwareAccelerated()方法,可以用于判断当前View和Canvas是否处于硬件加速中。

  • View.isHardwareAccelerated()

    如果View的isHardwareAccelerated()方法返回true,仅仅表示该View被加入到一个处于硬件加速的Window中,其有可能仍然使用一个非硬件加速的Canvas进行实际的渲染。所以,通常来说View的isHardwareAccelerated()方法实际用处不太大。

  • Canvas.isHardwareAccelerated()

    我们在View的onDraw回调方法中可以得到Canvas对象,如果Canvas的isHardwareAccelerated()方法返回true,那么表示当前Canvas是用GPU硬件加速渲染的,如果返回false就表示是用软件渲染的。通常,判断当前Canvas是否处于GPU硬件加速中对于绘制自定义的View来说比较重要,下面会解释。


硬件加速时2D图形绘制的局限

开启GPU硬件加速会提升程序的绘图效率,但是也存在一定的局限性。

  1. 启用GPU硬件加速会增加内存的使用。
  2. Android中有些2D绘图API在GPU硬件加速时不能使用或者要到某个指定的版本才能使用。
    • Canvas

      以下为Canvas中在GPU硬件加速时受限制的功能:

      第一列是受限制的方法,第二列是开始支持的API Level,红叉代表到目前还不支持。

    • Paint

      以下为Paint中在GPU硬件加速时受限制的功能:

    • Xfermode

      以下为Xfermode在GPU硬件加速时受限制的功能:

    • Shader

      以下为Shader在GPU硬件加速时受限制的功能:

    • Canvas缩放

      Android中硬件加速的2D渲染管线最初只支持无缩放的绘图,这会导致在将缩放比例设置为很大的时候,绘图质量会明显降低。最初,GPU加速下的2D绘图操作会被渲染成一个缩放比例为1.0的纹理,然后GPU会将它缩放到指定比例尺。在API Level小于17的时候,随着缩放比例scale的变大,绘图质量就更加难以保证。下面的表格表示了从什么版本开始Android能在GPU硬件计算下正确处理2D图形的大比例缩放问题:

    • 现在我们开发的App一般将targetSdkVersion写为最新版本,肯定大于API Level 14了,并且市场上的手机绝大部分都是Android 4.0以上的,所以我们现在开发的App默认情况下在绝大部分手机上基本都是默认开启了GPU硬件加速的。如果我们自己要自定义一个View,我们要重写其onDraw方法,通过调用各种绘图方法实现复杂的效果,但是如果我们调用的API在GPU硬件加速下不支持的话,就画不出我们想要的效果,举个例子,比如我们想在自定义View中绘制一个具有模糊效果的椭圆,需要调用画笔Paint的setMaskFilter()方法,但是我们通过上面的受限API列表可以发现,在GPU硬件加速下,Pait的setMaskFilter()方法不被支持,虽然调用不报错,但是不会起到任何效果。为了画出我们想要的效果,我们可以通过View的setLayerType(View.LAYER_TYPE_SOFTWARE, null)方法单独把我们的View禁用掉GPU硬件加速,这样在软件渲染模式下所有的2D绘图API都可以正常使用了。
    • 最后有点需要说明,上述Android在GPU硬件加速下2D图形绘制API存在的局限问题是基于当前最新API Level 23的,随着以后更新Android版本的发布,可能上述受限API会逐渐在GPU下得到更好的支持。

希望本文对大家初步了解Android中GPU硬件渲染2D图形有所帮助,后面会写文章深入探讨Android在GPU硬件渲染下绘制2D图形的Display List机制。

相关阅读:

我的Android博文整理汇总

Android中Canvas绘图基础详解(附源码下载)

版权声明:本文为博主原创文章,未经博主允许不得转载。如果觉得文章不错,记得顶一下!如果有疑问觉得文章中有错误,欢迎大家在评论中给我留言指正,看到会及时回复,多多交流

时间: 2024-10-11 09:52:18

Android中GPU硬件加速控制及其在2D图形绘制上的局限的相关文章

GPU硬件加速的那些优秀的资源总结

问题1:transform动画为什么没有经过大量的重绘? 解答:为什么 transform 没有触发 repaint 呢?(1)简而言之,transform 动画由GPU控制,支持硬件加速,并不需要软件方面的渲染.(2)浏览器接收到页面文档后,会将文档中的标记语言解析为DOM树.DOM树和CSS结合后形成浏览器构建页面的渲染树.渲染树中包含了大量的渲染元素,每一个渲染元素会被分到一个图层中,每个图层又会被加载到GPU形成渲染纹理,而图层在GPU中transform 是不会触发 repaint 的

GPU硬件加速

现代浏览器大都可以利用GPU来加速页面渲染.每个人都痴迷于60桢每秒的顺滑动画.在GPU的众多特性之中,它可以存储一定数量的纹理(一个矩形的像素点集合)并且高效地操作这些纹理(比如进行特定的移动.缩放和旋转操作).这些特性在实现一个流畅的动画时特别有用.浏览器不会在动画的每一帧都绘制一次,而是生成DOM元素的快照,并作为GPU纹理(也被叫做层)存储起来.之后浏览器只需要告诉GPU去转换指定的纹理来实现DOM元素的动画效果.这就叫做GPU合成,也经常被称这种借助于显卡的优势改变渲染操作:通常被笼统

Chrome 浏览器 用GPU硬件加速 让你的web 网页飞起来

摘要:Chrome 浏览器 用GPU硬件加速 让你的web 网页飞起来 安迪儿日前看到这篇介绍,好奇的试了一下 Google Chrome 8.X 版号三级跳,硬件加速再等等 就把原来的chrome 由原来的Stable稳定版本又再更新成Dev开发版本(直接点下去安装就换了) PS:10/21因为安迪儿的好朋友阿舍谈到关于Ubuntu Chrome Dev的事,安迪儿找了一下 用Ubuntu.Linux的朋友们,请到这边捉自已要的Chrome dev版本Subscribing to a chan

Android动画之硬件加速

你的动画写出来卡嘛?流畅嘛 如果你想提升动画的性能,那就是用它-hardware layers. During animations your views may be redrawn each frame. If you use view layers, instead of having to redraw each frame, views render once into an off-screen buffer which can be reused. In addition, har

CSS3 GPU硬件加速

1.代码(未添加GPU加速代码) 1 <!DOCTYPE html> 2 <html lang="zh-CN"> 3 4 <head> 5 <meta charset="UTF-8"> 6 <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> 7 <meta name="viewp

Android中Canvas绘图之PorterDuffXfermode使用及工作原理详解

概述 类android.graphics.PorterDuffXfermode继承自android.graphics.Xfermode.在用Android中的Canvas进行绘图时,可以通过使用PorterDuffXfermode将所绘制的图形的像素与Canvas中对应位置的像素按照一定规则进行混合,形成新的像素值,从而更新Canvas中最终的像素颜色值,这样会创建很多有趣的效果.当使用PorterDuffXfermode时,需要将将其作为参数传给Paint.setXfermode(Xfermo

Android中自定义View、ViewGroup理论基础详解

Android自身提供了许多widgets,但是有时候这些widgets并不能满足我们的需求,这时我们就需要自定义View,本文会详细说明自定义View的各种理论基础,只有理解了这些知识,我们才能更好地实现各种功能的控件. 我觉得自定义View中最重要的部分就是绘图和交互,自定义的绘图使得你的View与众不同,交互使用户可以与你的View进行交互,而绘图的前提是View的量算与布局,交互的基础是触摸事件,所以量算.布局.绘图.触摸事件这些是自定义View的核心. 除此之外,一个设计友好的自定义V

Android硬件加速介绍与实现

概述 在手机客户端尤其是Android应用的开发过程中,我们经常会接触到"硬件加速"这个词.由于操作系统对底层软硬件封装非常完善,上层软件开发者往往对硬件加速的底层原理了解很少,也不清楚了解底层原理的意义,因此常会有一些误解,如硬件加速是不是通过特殊算法实现页面渲染加速,或是通过硬件提高CPU/GPU运算速率实现渲染加速. 本文尝试从底层硬件原理,一直到上层代码实现,对硬件加速技术进行简单介绍,其中上层实现基于Android 6.0. 硬件加速对App开发的意义 对于App开发者,简单

4.1.Android的硬件加速官方文档

参考 https://developer.android.com/guide/topics/graphics/hardware-accel.html 硬件加速背景知识 在手机客户端尤其是Android应用的开发过程中,我们经常会接触到"硬件加速"这个词.由于操作系统对底层软硬件封装非常完善,上层软件开发者往往对硬件加速的底层原理了解很少,也不清楚了解底层原理的意义,因此常会有一些误解,如硬件加速是不是通过特殊算法实现页面渲染加速,或是通过硬件提高CPU/GPU运算速率实现渲染加速. 本