Android4.0以后,系统默认开启硬件加速来渲染视图
两者都是从SF获取一块内存,绘制都是在APP端,绘制好后都是通知SF去进行合成图层
真正的区别:绘制是通过CPU还是GPU完成的视图绘制。
对应区别在代码中的体现是ViewRootImpl中:
private void draw(boolean fullRedrawNeeded) {
...
if (!dirty.isEmpty() || mIsAnimating || accessibilityFocusDirty) {
//是否使用硬件加速 在前面setView的时候已经创建好了mAttachInfo.mHardwareRenderer
if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled()) {
dirty.setEmpty();
mBlockResizeBuffer = false;
//硬件加速绘制 使用HardwareRenderer进行绘制
mAttachInfo.mHardwareRenderer.draw(mView, mAttachInfo, this);
} else {
//软件绘制
if (!drawSoftware(surface, mAttachInfo, xOffset, yOffset, scalingRequired, dirty)) {
return;
}
如果开启了硬件加速则调用mHardwareRenderer.draw绘制;
没有开启则只是调用drawSoftware方法
drawSoftware:利用Surface的lockCanvas向SF申请一块匿名共享内存,并获取一个普通的SkiaCanvas之后方便使用Skia库图形绘制,onDraw中对这个Canvas的操作就是对那块匿名共享内存的操作,使用之前的Skia图形库进行渲染接着SF之后去这块内存中拿到图层数据进行合成。
软件绘制的Skia图形库渲染是CPU工作完成;8.0之后,Skia间接调用OpenGl,OpenGL间接操作GPU可降低CPU压力
比如drawText,DrawLine会被抽象成drawTextOp,DrawLineOp
如果是ViewGroup则递归调用子View来缓存子View的DrawOp树
构建完所有的DrawOp后,交给RenderThrea去处理,区别来了:软件绘制是在主线程,硬件加速是在单独的RenderThread中去完成绘制的
摘一个网上的图:
DrawOp树最后是缓存在了DisplayList中,不像软件绘制是直接将绘制数据同步到匿名共享内存中。
在performTraversals中提前获取共享内存,不像软件绘制那样等到performDraw再lockCanvas获取。
通过EGL Api获取一个EGLSurface封装原Surface的绘图数据,并设定为当前渲染窗口绑定到RenderThread中,RenderThread就会渲染绑定的Surface。
这里感觉像是和离屏渲染那个差不多,合并绘制纹理阴影之类的,因为画家算法是从远到近绘制的,绘制完之后如果之后的图层会影响之前的图层是无法进行操作的,所以礼品渲染将这块需要稍后可能会处理的图层单独放到一个离屏缓冲区中之后再添加。
Layer就是Surface,比如SurfaceView和TextureView
OpenGl利用GPU操作渲染数据,并将数据同步给SF
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。