1.3 屏幕坐标系
1.4 LCD 时序
CRT 的电子枪从上到下依行扫描,扫描完成后显示器就会呈现一帧画面,随后回到原点继续下一次扫描。为了把显示器的显示过程和系统的视频控制器进行同步,显示器会用硬件时钟产生一系列的定时信号。
当电子枪换到新的一行准备扫描时,显示器会发出一个水平同步信号(horizonal synchronization),即 HSync;
当一帧画面绘制完成后,电子枪回到原点,准备下一帧前,显示器会发出一个垂直同步信号(vertical synchronization),即 VSync;
1.4.1 HSYNC 时序
显示器通常会以固定频率进行刷新,该刷新率就是 VSync 信号产生的频率。
CLK:像素时钟;像素数据只有在时钟上升/下降沿时才有效;
ENB:数据使能信号;ENB = 1时,CLK 信号到达时输出有效数据;
HBP:行同步信号的前肩,水平同步信号的上升沿到 ENABLE 的上升沿的间隔;
HSW:水平同步信号的低电平(非有效电平)持续时间;
HFP:行同步信号的后肩,ENABLE 的下降沿到水平同步信号的下降沿的间隔;
从 HSYNC 的下降沿开始,等待两个 CLK 产生一个上升沿,中间在等待一个 HBP 的时间后开始传输一行的像素数据,像素数据只有在像素时钟的上升沿/下降沿才会写入,经过 N 个像素时钟后成功将一行数据写入 D1 - Dn:
同样的,在两帧画面之间也存在间隔:
VSW:VSYNC信号下降沿到上升沿之间的时间;
VBP:帧同步信号的前肩; VFP:帧同步信号的后肩;
VPROCH:消隐区,指的是 VSW+VBP+VFP 的时间段;在 VPROCH 之间不更新像素点的颜色。
在一个 VSync 周期内是由多个 HSync 周期组成,VSync 的个数就是屏幕在 Y 方向的像素点个数,也就是屏幕有多少行像素点;每个 HSync 周期内传输一行内所有的像素点的数据。
通常panel厂商还会给出类似下图:数据是以行为单位写入,HSync 是协调行与行之间的同步信号,多个行依次写入构成一帧数据,帧与帧之间通过 VSync 信号来同步协调。
当多帧画面依次输入到屏幕,且速度达到 60s/帧,人们就可以看到流畅的运动画面。下图为 VSync 和 HSync 同步两帧画面的切换时序,以及 VPROCH 在中间的位置关系。
在 VPROCH 结束/开始 时 DDIC 会向 SOC 发送一个中断信号( TE 信号 ),SOC 这边通过 TE 信号来判断上一帧数据是否已被 DDIC 读走,进而决定是否可以将 buffer 写入下一帧数据。
从 SOC ——> DDIC ——> panel 画面更新过程:
首先 SOC 准备绘制画面 A;
DDIC 上一帧画面更新完毕进入 VPROCH,同时向 SOC 侧发送 TE 信号;
SOC 接收到 TE 信号后,A画面的数据开始通过 DSI 总线向 DDIC 传输( DSI write );
当 VPROCH 时间结束时,开始这一帧数据,从数据变成像素点颜色的过程 ( Disp Scan ):
Disp Scan 是以行为单位,将 GRAM 内一行的数据内容 通过改变电流电压的方式改变 Panel 上像素点的颜色,进而实现一行画面的更新
;
接下来,Disp Scan 将一定的速度逐行读取 GRAM 的内容;同时 DSI Write 也在进行;
由于 DSI Write 比 Disp Scan 早了一个 Vproch 的时间,所以 Disp Scan 扫描的数据都是 A 画面的数据。
这样人眼会看到的画面 “逐渐”出现在 panel 上,当 A 画面的所有行都通过 Disp Scan 到达屏幕后,下一个 Vproch 开始,DDIC 再次向 SOC 发送 TE 信号,下一帧 B 画面的数据通过 DSI 总线传输到 DDIC,循环可以将连续的 A、B、C 画面更新到屏幕上。
图 1:
上图绘制中,GRAM 内数据会出现:一半是新画面的数据,一半是旧画面的数据,那么从 GRAM 角度上看画面是"撕裂",那么如何保持画面完整:
DSI write 记作写,Disp Scan 记作读;正常情况下,会将 读 & 写速度 差不多;
写 是在进入 Vproch 时就开始了,读 是在离开 Vproch 时开始的,所以正常情况下要求 写先于读,这样才能保证读到的是同一帧画面的数据;
图 2:
但是 读写 速度会受到环境/各种电气因素影响,实际中会存在波动:读写两条线较近的时候,由于速度波动存在会出现两条线交叉的情况,那么导致读取的 — 先后两帧的数据,出现花屏现象。
图 3:
为了避免因速率问题导致的花屏现象,会放大 Vproch 的时间让读写尽量拉开距离,可以减少出现花屏现象的概率,如图3。
3.1 APP ——> SF
之后 APP 通过 dequeueBuffer 拿到画布,通过 queueBuffer 来提交绘制好的数据:
HWC Service 负责将 SF 送来的图层做合成,形成最终的画面,然后通过 drm 的接口更新到屏幕上。
3.2 SF——> HWC Service
3.3 HWC Service——> kernel
HEC Service 通过接口向 kernel 提交合成数据,通过 ioctrl 调用到 kernel。
3.4总结
APP 绘制的画布是由 SF 提供,而画布是一块共享内存;APP 向 SF 申请到画布,是将共享内存的地址映射到自身进程空间。
APP 负责在画布上作画,完成后的画面提交给 SF,这一步提交过程不是简单的内存复制,而是把共享内存的控制权交还给 SF,SF 把拿来的多个应用的共享内存送给 HWC Service去合成
HWC Service把合成的数据交给 DRM 去输出完成 app画面显示到屏幕上的过程。
其中,为了有效的利用时间,所以共享内存可能不只一个,所以需要设计一个机制管理 buffer 的控制权,就是 BufferQueue。
4. 应用画面更新总结
首先遍历所有的 layer,找到哪些layer有上帧,通过 acquireBuffer 把 buffer 拿出来,通知 HWC Service 参与合成,最后调用 HWC Service的 presentDisplay 接口告知 HWC Service SF 的工作已完成。
HWC Service 收到合成任务后开始合成数据,在SF 调用 presetDisplay 时调用 DRM 接口,通知 kernel 向 DDIC 发送数据;若有 TE 信号来提示已进入 VPROCH,DRM 驱动会马上开始通知 DSI 总线向 DDIC 传输数据,同时 panel 的 Disp Scan 也在进行中,传输完成后这一帧画面完整的显示在屏幕上。