---------------------
做IOS开发,特别是做界面部分的同学,不得不掌握图形的渲染原理。这里包括不限于图形渲染机制、离屏渲染、png图片渲染等重要问题。
下面以一个系列文章分享下。
屏幕图像显示原理
讲到渲染,就要从计算机的屏幕图像显示开始。在计算机的发展过程中,屏幕图像显示的发展又分了两个阶段:随机扫描,光栅扫描。
随机扫描
电子束是随机的移动,即电子束可以按照显示命令任意方向上自由移动。例如要在计算机上显示一个三角形,那么电子束就按照三角形的边的位置,直接移动,从而绘制出需要的图形。这种扫描方式只能绘制直线、三角形等简单图形,要绘制人物、风景等复杂图形就实现不了。只能通过光栅扫描来实现了。
光栅扫描
电子束依照固定的扫描线和规定的扫描顺序进行扫描。电子束先从荧光屏左上角开始,向右扫一条水平线,然后迅速地回扫到左边偏下一点的位置,再扫第二条水平线,照此固定的路径及顺序扫下去,直到最后一条水平线,从而完成了整个屏幕的扫描。这也是我们常说的逐行扫描。通过这种方式就能绘制人物、风景等复杂图形了。
总结成一句话:随机扫描、光栅扫描都是将二进制数据转换成可见的视图。
渲染的部件
这里我们还需要搞清楚一点:我们计算机渲染是由哪个部件来完成的, CPU还是GPU?答案是GPU。若从普通用户的角度来说,那就是我们的显卡(包括独立显卡和集成显卡)来完成的。
那为什么是GPU呢?一个原因是GPU擅长于简单的大规模并发计算和协同处理,二是CPU偏向于复杂的控制运算。就好比GPU是小学生,处理一些简单的加减运算,CPU就像大学教授,懂微积分运算。像图形渲染属于简单的运算,只要找来十几个小学生计算就可以了, 没有必要去找大学教授用微积分来计算。
但这里特别说明下:IOS平台的png格式的图片解码是由CPU来完成的,而非GPU。这点先记下。后面会讲到。
GPU渲染流水线:
经过前面的讲述,图形经过GPU就会变成我们需要显示的图片。那它内部是怎么个过程呢?
GPU 图形渲染具体分以下六个阶段:
Step1.顶点着色器(Vertex Shader)
Step2.形状装配(Shape Assembly)
Step3.几何着色器(Geometry Shader)
Step4.光栅化(Rasterization)
Step5.片段着色器(Fragment Shader)
Step6.测试与混合(Tests and Blending)
这个过程很复杂,就不详细的讲述。反正通过以上六个步骤,就能得到我们需要显示的图片。
帧缓冲区
经过前面六步处理,数据都会进入帧缓冲区,再从帧缓冲区到显示控制器,最后在屏幕上显示。
帧缓冲区是一个很重要的概念,所有要显示的图片都要经过它,它本身是一块内存缓冲区,其中包含完整视频帧中所有像素的数据。其大小由图形的分辨率、色深或调色板大小来决定。
上面讲了各个具体的概念,再统一起来讲下图形渲染机制。
渲染机制
以IOS开发中UIButton设置一张背景图片为例,先调用了UIButton的SetImage函数,该函数会调用Core Animation 框架,该框架又调用OpenGL ES/Metal底层库,然后进入GPU模块,再经过GPU的渲染流水线,形成图形并放入帧缓冲区中,最终由显示控制器处理并显示在屏幕上。以下是图示
小结:
1.现在的图形/图像都是光栅扫描完成.
2.图形/图像的渲染是由GPU完成的。
3.图像/图形的渲染流程是:图片经过OpenGL ES/Metal底层库进入GPU模块,再经过GPU的渲染流水线,形成的位图图形并放入帧缓冲区中,最后由显示控制器负责显示。
图片撕裂
具体图片撕裂样式见下图。
出现此问题的原因:在显示控制器还在光栅视频帧A时,GPU已经完成了B帧的处理,然后会把B帧的数据放入帧缓冲区。这样显示控制器在光栅屏幕的时候,拿到的是B帧数据。从而导致了屏幕的上部分是A帧(旧数据),下部分是B帧(新数据).
那针对这个问题,怎么解决呢?其实也简单,就是在刷A帧的时候,帧缓冲区的数据不更新,直到屏幕中A帧最后一条刷新了。这就是垂直扫描的同步信号。简单来说,是对帧缓冲区加了一把锁,在起始扫描A帧的时候,加上锁(不允许更新帧缓冲区),当扫描到A帧的最后一行时,发送一个垂直同步信号,释放锁。
视频卡顿
当一屏幕扫描完,垂直扫描信号发出,但是CPU/GPU还没有完成新一帧的渲染工作,那么显示控制器还是继续显示上一帧的数据,这个现象就是卡顿,也叫掉帧。解决这个问题的方法是多缓冲区,其中iOS设备采用的时候双缓冲区(Double Buffering),安卓设备是采用三缓冲区.比较单缓冲区,多缓冲区能减少卡顿次数.
其实呢,视频卡顿本质来说是:CPU/GPU处理速度太慢,光栅一屏数据,还没有完成新图片的渲染。这个时候,我们就要想想我们业务做了些什么业务?让CPU/GPU这么耗时。
在实际情况下,iOS设备采用了垂直同步信号+双缓冲区 两个方案来解决图形的撕裂和卡顿问题。
-----好的,篇幅太长,先分享到这里。
参考资料:
深度好文:关于图形渲染以及离屏渲染