使用过Linux framebuffer的人都知道,我们需要在屏幕上显示一幅图像时,只需要将framebuffer mmap到用户空间,然后直接写这块内存即可,操作的结果会立即反映在display上。作为分析Android display path的基础知识,我先来讲讲Linux这部分的原理,如下图所示:
MDP会以一个固定的刷新率取得framebuffer中的数据送往panel,只要我们更新了framebuffer, 更新的内容会在一个刷新周期内反映在panel上。同时,Linux display path还支持可选的pan_display操作,减少刷屏的抖动问题。原理是当前显示的framebuffer并不是用户操作的framebuffer,待用户更新完back framebuffer后,调用pan_display,使得front framebuffer和back framebuffer调换,并强制刷新。
接着我们来分析一下Android中的display path,Android 区别于Linux,它强制定义了两倍于屏幕大小的framebuffer用于display。每次需要更新panel的数据时,都会调用ioctl()函数重新设置DMA的寄存器,指定当前的framebuffer偏移地址。另外,整个display path也做了很大的变动,如图所示:
Framebuffer API不再是对MDP DMA hal驱动的简单包装,进一步封装了MDP PPP hal驱动,buffer中的数据首先经过MDP PPP,完成图像的缩放/de-interlace/csc等操作后放入framebuffer,之后由MDP DMA写入lcd.