android q hwui有什么变化,Android HWUI硬件加速模块浅析

Android HWUI硬件加速模块浅析

什么是硬件加速(What)

传统软件的UI绘制是依靠CPU来完成的,硬件加速就是将绘制任务交由GPU来执行。GPU相比CPU更加适合完成光栅化、动画变换等耗时任务,在移动设备上比起使用CPU来完成这些任务,GPU会更加省电些,带来的用户体验也会更佳。

为什么要硬件加速(Why)

Android的硬件加速的底层实现是基于OpenGL ES接口向GPU提交指令来完成绘制的。相对于CPU实现的软绘制,硬件加速的帧率会高于CPU,效能更高。屏幕分辨率越大(尤其对于高清电视而言),硬件加速的优势更加明显。

下图是Android 5.0的HWUI绘制执行流程:

acb8664209fe068681101f0d2a6018c6.png

源码位于目录android/platform/framework/base/libs/hwui喎?http://www.Bkjia.com/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwcmUgY2xhc3M9"brush:java;">

public class View implements Drawable.Callback, KeyEvent.Callback, AccessibilityEventSource {

......

public void buildLayer() {

......

final AttachInfo attachInfo = mAttachInfo;

......

switch (mLayerType) {

case LAYER_TYPE_HARDWARE:

updateDisplayListIfDirty();

if (attachInfo.mHardwareRenderer != null && mRenderNode.isValid()) {

attachInfo.mHardwareRenderer.buildLayer(mRenderNode);

}

break;

case LAYER_TYPE_SOFTWARE:

buildDrawingCache(true);

break;

}

}

......

}

当View的LayerType设置为HARDWARE时,View就会绑定到一个OpenGL ES的FrameBufferObject上去,如果要对这个View进行Animation(Alpha,Rotation,etc.),会将这个FrameBufferObject渲染至Texture(2D),然后再进行动画的渲染,这样有一个坏处,消耗的内存增加了。

硬件加速的实现(How)

独立的渲染线程

在Android 5上,ThreadedRenderer的出现减轻了主线程的负担,可以更快的响应用户的操作。

Deferred Display List

26a0e27d18de383e9f67a655f965ee95.png

DisplayList记录了绘制操作和状态,主线程将它们提交至OpenGL渲染器,由渲染器执行最终的DrawCall。

Android 4.4之后,HWUI模块引入了Deferred Display List,它在Display List的基础上做了一些优化,比如剔除过绘制的区域、对DrawCall进行分批或合并,在一定程度上提升了绘制的性能。

创建纹理集

40843e9e36ecf97e590751772cc7665d.pngseo8L3N0cm9uZz6jrMq5VUnSwMi7xNy5u9X9yLe75tbGoaM8L3A+DQo8L2Jsb2NrcXVvdGU+DQo8cD7I57n7yeixuNans9ZPcGVuR0wgRVMgMy4wo6xBbmRyb2lku+HKudPDPHN0cm9uZz5QaXhlbEJ1ZmZlck9iamVjdLDztqg8L3N0cm9uZz7Ktc/WzsbA7bXE0uyyvcnPtKujrNXi0fnX9rXEusO0ptTa09rNqLn907PJ5Le9yr2jqGdsTWFwQnVmZmVyo6m4/LzTuN/Qp7XEyc+0q87GwO3K/b7d1sFHUFWho8/Cw+bV4rbOtPrC68C019TT2tfAw+a2y7XEyrXP1qOs0sa2r7bLtcTKtc/Wsu7S7LK7tPOhozwvcD4NCjxwcmUgY2xhc3M9"brush:java;">

// 绑定纹理单元和PBO

glBindTexture(GL_TEXTURE_2D, textureId);

glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pboIds[index]);

// 将PBO的像素复制到纹理中去

glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, WIDTH, HEIGHT, GL_BGRA, GL_UNSIGNED_BYTE, 0);

//准备上传下一份纹理

glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pboIds[nextIndex]);

//这里如果直接调用glMapBuffer会引起OpenGL状态机的一个同步检查(开销较大),但是使用BufferData的话就不会,他可以直接分配完数据返回

glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, DATA_SIZE, 0, GL_STREAM_DRAW_ARB);

//将GPU数据映射至内存

GLubyte* ptr = (GLubyte*)glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY_ARB);

if(ptr) {

updatePixels(ptr, DATA_SIZE); //直接更新纹理数据

glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB); // 释放映射的缓冲区

}

glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);

ATLAS的使用减少了GPU显存的消耗,以及纹理单元(Texture Unit)绑定调用(Resource Binding)的开销。

合并DrawCall

645a4dddb92a9ce385d54d8086616463.gif

Android硬件加速的过程中并没有启用深度测试(DepthTest),所有的UI绘制都是按照绘制的次序展示在屏幕上。由于OpenGL ES的驱动实现的复杂性,每个GL的绑定调用以及GL状态的切换都是昂贵的,所以才引入了Deferred Display List对DrawCall合并以及分批,相关类,如上图。

字体绘制

04881ae24768b009855934c773150b5e.png

文字的渲染也是一个令人头疼的问题,APP的文字渲染不像游戏中那样的简单,通常游戏发布的时候可以预先将固定的文字转换成单张的纹理,渲染文字时直接映射纹理坐标即可。Android底层对文字字形纹理数据进行了Cache。Android使用了Skia和第三方开源字体库(FreeType)对字体进行栅格化。

be8a788e8bf364aa0b54c6dd155c4acf.png

硬件加速的改进

iOS的UI绘制使用了Multiple GL Context,在iOS 8之后又引入了Metal Framework,原生支持多线程UI渲染,Android由于GL驱动以及GPU厂商实现的差异无法很好地榨干GPU的机能,但是在下一代的图形API(Vulkan,驱动变薄、支持多线程)普及之后,仍然有较大的优化空间,UI流畅性可以进一步提升。

http://www.dengb.com/Androidjc/1039337.htmlwww.dengb.comtruehttp://www.dengb.com/Androidjc/1039337.htmlTechArticleAndroid HWUI硬件加速模块浅析 什么是硬件加速(What) 传统软件的UI绘制是依靠CPU来完成的,硬件加速就是将绘制任务交由GPU来执行。GPU相比...

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值