前言:

        断断续续跟Android的skia库打了两年交道,如今交接掉了,便写写关于skia的一些知识,也算了结一段职业生涯。
找了找网上关于skia的文章,基本上都过时了,讲得也不怎么深入。虽然Skia只是一个2D引擎,但其深度优化的算法、完善的渲染体系和精炼的代码框架,还是很值得借鉴的。

        PS:文章所依据的代码为目前最新的Android 5.0.2。

基本章节规划如下:
1、Skia的上下文(即本章)
2、Skia基本渲染流程与框架
3、Skia图像绘制分析
4、Skia路径绘制分析
5、Skia文本绘制分析
6、Skia编解码架构分析

7、区域解码分析
8、Skia-gpu简介
9、Skia的性能瓶颈分析
10、延迟渲染机制


一、Skia在Android中的地位


1、规定2D绘制API

2、规定图像数据结构

3、承担编解码调度和软件渲染职责


二、Android系统中主要使用Skia的场景

android radialgradient渲染 安卓gpu渲染程序skia_ui

Skia调用关系简图



1、界面绘制(lockCanvas——draw——unlockCanvas流程)

(1)UI控件,未开启硬件加速。由performTravelsals——drawSoftware调入。

Android显示系统是最复杂的Android最复杂的子系统,没有之一,这里只说明软件绘制时的一个基本过程:

a、计算布局,看是否需要更新View。

b、计算所有需要更新的View的区域,计算其最小外包矩形,即dirtyRect

c、由Surface去Lock一个Canvas,Lock时指定dirtyRect,这里涉及gui的buffer轮换机制,会去获取一块未在显示的Buffer,由于换了buffer,在gui模块会去拷贝上一帧非dirtyRect的部分。

d、执行根View的draw方法,递归调用所有子View的onDraw方法。由于Canvas对应的是软件绘制的canvas,所有绘制操作经过Canvas——SkiaCanvas——SkCanvas的流程,由skia引擎执行。(AndroidL上在jni(libandroid_runtime)处作了一层SkiaCanvas的封装,4.4及以前是Canvas——SkCanvas)

e、完成绘制,让Surface去unlockCanvas,将绘制好的Buffer送显。

(2)SurfaceView,这个是由应用显式实现lockCanvas——draw——unlockCanvas流程。


2、图像处理


这种情况下,开发者自行基于目标Bitmap创建Canvas,调用Canvas的API绘制图像,一般是作图像的缩放、旋转处理,也可以加入渐变特效。(不是 lockCanvas 或 继承 onDraw 方法中传入的Canvas,就别想拿去上屏了)


3、图像编解码


Skia对各种类型的图片作了适配,提供统一的接口,开发者调用BitmapFactory,BitmapFactory进一步调用jni——skia。

(1)关于图像全解,这部分调用逻辑看上去简单,实际上对于输入输出流的处理还是比较复杂的,涉及Java的流——Skia规定的流——对应解码库的流两重转换。

(2)关于区域解码,这部分是google为平衡内存——性能——显示速度而设计的方案,一些Android机器上的图库打开照片时有一块一块渐渐清晰的过程,就是区域解码然后局部刷新的结果。

区域解码分成两步:

a、创建tileIndex,以便查找某个区域所对应的码流位置。

b、解码:输入指定区域,按照tileIndex查找对应码流,将对应区域的图片解出来,这个过程一般会调用多次。



4、番外:webview软件渲染


由于libchromeview将libskia以静态方法集成进去,便跟系统的skia库没什么关系了。对Android系统而言是统一的webview显示框架。




三、skia相关的库简介

android radialgradient渲染 安卓gpu渲染程序skia_编解码_02

Skia相关模块


1、调用skia的库

libandroid_runtime:framework.jar的jni实现,链接framework和lib库的桥梁

hwui:2D硬件加速库,使用skia的数据格式

libchromeview:浏览器引擎,webview相关



2、Skia使用的库


(1)图片编解码库

libjpeg

libpng

libgif

webp

(2)字体解析

freetype

具体内容会在后续章节中讲述。