正常显示流程
Xorg无旋转时显示流程如下图所示:
FB Root为屏幕对应的帧存,屏幕显示的最终效果渲染到该帧存中。CRTC负责读取FB Root的数据,并按照用户设置的分辨率时序参数进行输出。VGA或者DVI作为output,将CRTC的输出进行A/D转换或者编码后送给显示器显示,对FB Root的更新会实时显示到屏幕上。
旋转显示流程
Xorg带旋转时显示流程如下图所示:
旋转模式下,屏幕显示内容先渲染到FB Root中,然后由Xorg Block Handler(关于Xorg Handler的介绍可以参考另一篇文章:Xorg Handler简介)将FB Root的数据旋转后存入FB Rotate中,CRTC绑定到FB Rotate进行显示。很明显这种情况下,比正常显示多了一个帧存和无休止的旋转操作,而且对FB Root的更新不会实时显示到屏幕上,必须等旋转操作完成后才能显示出最终效果。
驱动对旋转的支持
驱动要支持旋转功能必须要实现以下4个xf86CrtcFuncsRec结构体成员函数:
- shadow_allocate: 负责分配FB Rotate帧存;
- shadow_create: Xorg无法直接操作帧存,该函数创建一个Xorg可操作的Pixmap对象,并将FB Rotate绑定到其中;
- shadow_destroy: 销毁FB Rotate和对应的Pixmap;
- set_mode_major: 初始化旋转参数、安装用于旋转的Block Handler;配置CRTC分辨率,并绑定到FB Rotate;配置output并绑定到CRTC;
xf86CrtcRotate函数
set_mode_major函数中要实现的初始化旋转参数和安装旋转Block Handler由Xorg xf86CrtcRotate函数实现。
该函数先根据屏幕宽高、旋转方向、输入矩阵等参数计算出旋转相关的参数:
Bool
xf86CrtcRotate(xf86CrtcPtr crtc)
{
ScrnInfoPtr pScrn = crtc->scrn;
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
PictTransform crtc_to_fb;
struct pict_f_transform f_crtc_to_fb, f_fb_to_crtc;
xFixed *new_params = NULL;
int new_nparams = 0;
PictFilterPtr new_filter = NULL;
int new_width = 0;
int new_height = 0;
RRTransformPtr transform = NULL;
Bool damage = FALSE;
if (pScreen->isGPU)
return TRUE;
if (crtc->transformPresent)
transform = &crtc->transform;
if (!RRTransformCompute(crtc->x, crtc->y,
crtc->mode.HDisplay, crtc->mode.V