撕裂
撕裂就是一张图在屏幕上明显表现为上下两截,而不是完整的一帧,撕裂源于数据传输。也就是说MIPI(LCD)读取framebuffer时,数据已经不是完整的了,通常来说内容被覆写了
屏幕的刷新机制
逐行扫描
无论是CRT时代,还是现在LCD或OLED,显示器刷新的原理一直没变,当它刷新一帧的时候并不是一次性把整个画面全部刷新出来,而是同一时刻只处理一个点,从上到下一行一行逐渐把图片绘制出来的。因为人眼的视觉暂停的,如果在短时间内处理完所有的点,就仿佛看到的同一帧画面
解决方案
- 在PC上,我们的显示系统默认采用的双Buffer机制,通过SwapBuffer切换前/后缓冲
如果采用单Buffer,会出现怎么样的场景?(当这个Buffer在屏幕上显示时,GPU绘制也在同时发生,撕裂将无可避免?)
但事实并非如此绝对,单Buffer机制并不必然导致屏幕撕裂。显示器在刷新屏幕上半部分的时候,GPU绘制下半部分就可以避免撕裂,这也被称为Strip渲染
Strip Rendering的想法就是,改变还没有显示出来的那部分Buffer,有2种不同的策略可供选择
- Beam Racing:改变下一步将显示的屏幕的那部分,因为我们想要跑到扫描线前更新还未被显示的那部分内存
- Beam Chasing:在扫描线之后更新画面
对优化延迟这个目的来说,Beam Racing策略会更好,但同时也更难实现。GPU需要保证在很紧的时间窗口完成渲染。这非常难保证,尤其在一个多线程的操作系统中,所有运作都发生在后台,同时,GPU可能会渲染到其他Buffer的区域中,所以Beam Chasing会更容易实现
- 回到双Buffer上来,即使使用了前后缓冲,撕裂仍是可能发生的,原因是GPU绘制速度快于显示器刷新速度,则后缓冲填满之后,前缓冲仍会被新数据覆盖
我们发现GPU速度既不能太快于显示器刷新速度,也不能太慢于显示器刷新速度,只有GPU与显示器步调一致才能不撕裂
这就需要VSync机制了,无论谁快了,都只能等待。如果GPU快了,则无法继续绘图,原地sleep。如果显示器快了,则继续刷新上一帧