php页面控制android硬件,Android硬件加速原理与实现

页面渲染背景知识:

页面渲染时,被绘制的元素最终转换为矩阵像素点(多维数组的形式),才能被显示器显示

页面由各种基本元素组成,例如圆形,圆角矩形,线段,文字,矢量图(常用贝塞尔曲线组成),Bitmap等

元素绘制时尤其是动画绘制过程中,经常涉及插值、缩放、旋转、透明度变化、动画过渡、毛玻璃效果,3D变换、物理运动、多媒体文件解码等运算。

绘制过程需要进行逻辑简单,但数据量庞大的浮点运算。

CPU与GPU结构对比

从结构上看,CPU的控制器较为复杂,而ALU数量较少,因此CPU擅长各种复杂的逻辑运算,但不擅长数学尤其是浮点运算。以8086为例,一百多条汇编指令大部分都是逻辑指令,数学计算相关的主要是16位加减乘除和移位预算。一次整形和逻辑运算一般需要1~3个机器指令周期,而浮点运算要转换为整形计算,一次运算可能消耗上百个机器周期。更简单的CPU甚至只有加法指令,减法用补码加法实现,乘法用累加实现,除法用减法循环实现。现在CPU一般都带有硬件浮点运算器FPU,但主要用于数据量不大的情况。CPU是串行结构,以计算100个数字为例,对于CPU的一个核,每次只能计算两个数,然后结果累加。

GPU是为了实现大量数学运算设计的。GPU的控制器比较简单,但包含了大量ALU。GPU的ALU使用了并行设计,且有较多浮点运算单元。

硬件加速的主要原理,就是通过底层软件代码,将CPU不擅长的图形计算转换为GPU专用指令,由GPU完成。

很多计算机中的GPU有自己独立的显存;没有独立显存则使用共享内存的形式,从内存中划分一块区域作为显存。显存可以保存GPU指令等信息。

Android UI渲染处理节点

在Android中,大多数应用的界面都是利用常规的View来构建的(除了游戏、视频、图像等应用可能直接使用OpenGL.ES)。

DisplayList

DisplayList是一个基本绘制元素,包含元素原始属性(位置,尺寸,角度,透明度等),对应Canvas的drawXxx()方法。

信息传递流程:Canvas(Java Api) -> OpenGL(C++ lib) -> 驱动程序 -> GPU

在Android 4.1以上版本,DisplayList支持属性,如果View的一些属性发生变化(比如Scale,Alpha,Translate),只需把属性更新给GPU,不需要生成新的DisplayList。

RendorNode

一个RendorNode包含若干个DisplayList,通常一个RendorNode对应一个View,包含View自身以及子View的所有DisplayList。

Android绘制流程

从ViewRoutImpl.performTraversals 到 PhoneWindow.DectorView.drawChild是每次遍历View树的固定流程,首先根据标志位判断是否需要重新布局并执行布局;然后进行Canvas的创建等操作开始绘制。

如果硬件加速不支持或者被关闭,则使用软件绘制,生成的Canvas即Canvas.class对象

如果支持硬件加速,则生成的是DisplayListCanvas.class对象

两者的isHardwareAccelerated()方法返回的值分别为false,true. View根据这个值判断是否使用了硬件加速。

View中的draw(canvas, parent, drawingTime) -> draw(canvas) -> onDraw() -> dispatchDraw() -> drawChild()这条递归路径(Draw路径),调用了Canvas.drawXxx()方法,在软件渲染是用于实际绘制;在硬件加速时,用于构建DisplayList。

View中的updateDisplayListifDirty -> dispatchGetDisplayList -> recreateChildDisplayList这条递归路径(DisplayList路径),仅在硬件加速的时候会经过,用于在遍历View树绘制的过程中更新DisplayList属性,并快速跳过不需要重建DisplayList的View。

硬件加速情况下,draw流程执行结束后,DisplayList构建完成,然后通过ThreadedRenderer.nSyncAndDrawFrame()利用GPU绘制DisplayList到屏幕上。

渲染场景

软件绘制

硬件加速

加速效果分析

页面初始化

绘制所有View

创建所有DisplayList

GPU分担了复杂计算任务

在一个复杂页面调用背景透明TextView的setText()方法,且调用后尺寸位置不变

重绘脏区所有View

TextView及每一级父View重建DisplayList

重叠的兄弟节点不需CPU重绘,GPU会自行处理

TextView逐帧播放Alpha/Transition/Scale动画

每帧都要重绘脏区所有View

除第一帧同场景2,之后每帧只刷新TextView对应RendorNode的属性

刷新一帧的性能极大提高,动画流畅度提高

修改TextView透明度

重绘脏区所有View

直接调用RendorNode.setAlpha更新

加速前需全页面遍历,并重绘很多View;加速后只触发DecorView.updateDisplayListIfDirty,不再往下遍历,CPU执行时间可忽略不计。

场景1中,无论是否加速,遍历View树,且走Draw路径。硬件加速后Draw路径不做实际绘制工作,只是创建DisplayList,复杂的绘制计算任务被GPU分担,已经有较大的加速效果。

场景2中,TextView设置亲厚尺寸位置不变,不会触发重新Layout。

软件绘制时,TextView所有区域即为脏区。由于TextView有透明区域,遍历View树过程中,和脏区重叠的多数View都要重绘,包括与之重叠的兄弟节点和他们的父节点,不需要绘制的View在draw(canvas, parent, drawingTime)方法中判断直接返回。

硬件加速后,也需要遍历View树,但只有TextView及其每一层父节点需要重建DisplayList,走的是Draw路径,其他View直接走DisplayList路径,剩下的工作都交给GPU处理。页面越复杂,两者性能差距越明显。

场景3中,软件绘制每一帧都要做大量绘制工作,很容易导致动画卡顿。硬件加速后,动画过程直接走DisplayList路径更新DisplayList的属性,动画流畅度得到极大提升。

场景4中,两者的性能差距更明显。简单修改透明度,软件绘制仍然要做很多工作;硬件加速后一般直接更新RenderNode的属性,不需要触发invalidate,也不会遍历View树(除了少数View可能要对Alpha做特殊响应,并在onSetAlpha()返回true,会走invalidate)。

软件绘制刷新逻辑

默认情况下,View的clipChildren属性为true,即每个区域不能超过其父View的范围。如果设置一个页面根布局的clipChildren属性为false,则子View可以超出父View的绘制区域。

当一个View触发invalidate,且没有播放动画,没有触发layout的情况下:

对于全不透明的View,其自身会设置标志位PFLAG_DIRTY。其父View会设置标志位PFLAG_DIRTY_OPAQUE。在draw(canvas)方法中,只有这个View自身重绘。

对于可能有透明区域的View,其自身和父View都会设置成标志位PFLAG_DIRTY

clipChildren为true时,脏区会被转换成ViewRoot中的Rect,刷新时层层向下判断,当View与脏区有重叠则重绘。如果一个View超出父View范围且与脏区重叠,但其父View不与脏区重叠,这个子View不会重绘。

clipChildren为false时,ViewGroup.invalidateChildInParent()中会把脏区扩大到自身整个区域,于是与这个区域重叠的所有View都会重绘。

总结:

CPU更擅长复杂逻辑控制,而GPU得益于大量ALU和并行结构设计,更擅长数学运算。

页面由各种基础元素(DisplayList)构成,渲染时需要进行大量浮点运算。

硬件加速条件下,CPU用于控制复杂绘制逻辑,构建或更新DisplayList;GPU用于完成图形计算,渲染DisplayList。

硬件加速条件下,刷新界面尤其是播放动画时,CPU只重建或更新必要的DisplayList,进一步提高渲染效率。

实现同样的效果,应尽量使用更简单的DisplayList,从而达到更好的性能(Shape替代Bitmap)。

本文参考

2018美团点评技术年货

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值