正常显示流程

  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.VDisplay,crtc->rotation,transform,&crtc_to_fb,&f_crtc_to_fb,&f_fb_to_crtc) &&xf86CrtcFitsScreen(crtc, &f_crtc_to_fb)) {/** If the untranslated transformation is the identity,* disable the shadow buffer*/xf86RotateDestroy(crtc);crtc->transform_in_use = FALSE;free(new_params);new_params = NULL;new_nparams = 0;new_filter = NULL;new_width = 0;new_height = 0;}else {

  接着调用驱动的shadow_allocate函数分配FB Rotate帧存:

/* Allocate memory for rotation */
if (old_width != width || old_height != height) {if (shadow || shadowData) {crtc->funcs->shadow_destroy(crtc, shadow, shadowData);crtc->rotatedPixmap = NULL;crtc->rotatedData = NULL;}shadowData = crtc->funcs->shadow_allocate(crtc, width, height);if (!shadowData)goto bail1;crtc->rotatedData = shadowData;/* shadow will be damaged in xf86RotatePrepare */
}

  最后将xf86RotateBlockHandler注册成为Screen的Block Handler用于完成旋转:

/* Wrap block handler */
if (!xf86_config->BlockHandler) {xf86_config->BlockHandler = pScreen->BlockHandler;pScreen->BlockHandler = xf86RotateBlockHandler;
}

xf86RotateBlockHandler函数

static void
xf86RotateBlockHandler(ScreenPtr pScreen,void *pTimeout, void *pReadmask)
{ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);/* Unwrap before redisplay in case the software* cursor layer wants to add its block handler to the* chain*/pScreen->BlockHandler = xf86_config->BlockHandler;xf86RotateRedisplay(pScreen);(*pScreen->BlockHandler) (pScreen, pTimeout, pReadmask);/* Re-wrap if we still need this hook */if (xf86_config->rotation_damage != NULL) {xf86_config->BlockHandler = pScreen->BlockHandler;pScreen->BlockHandler = xf86RotateBlockHandler;} elsexf86_config->BlockHandler = NULL;
}

  xf86RotateBlockHandler先调用xf86RotateRedisplay完成旋转功能,再调用Screen原始的Block Handler,最后判断是否还处于旋转状态,来决定是否继续注册为Screen Block Handler完成后续旋转操作。

xf86RotateCrtcRedisplay函数

  xf86RotateBlockHandler调用xf86RotateRedisplay函数进行旋转,xf86RotateRedisplay函数完成一些准备工作后,最后会调用xf86RotateCrtcRedisplay函数完成旋转操作。

static void
xf86RotateCrtcRedisplay(xf86CrtcPtr crtc, RegionPtr region)
{ScrnInfoPtr scrn = crtc->scrn;ScreenPtr screen = scrn->pScreen;WindowPtr root = screen->root;PixmapPtr dst_pixmap = crtc->rotatedPixmap;PictFormatPtr format = PictureWindowFormat(screen->root);int error;PicturePtr src, dst;int n = RegionNumRects(region);BoxPtr b = RegionRects(region);XID include_inferiors = IncludeInferiors;if (crtc->driverIsPerformingTransform)return;src = CreatePicture(None,&root->drawable,format,CPSubwindowMode,&include_inferiors, serverClient, &error);if (!src)return;dst = CreatePicture(None,&dst_pixmap->drawable,format, 0L, NULL, serverClient, &error);if (!dst)return;error = SetPictureTransform(src, &crtc->crtc_to_framebuffer);if (error)return;if (crtc->transform_in_use && crtc->filter)SetPicturePictFilter(src, crtc->filter, crtc->params, crtc->nparams);if (crtc->shadowClear) {CompositePicture(PictOpSrc,src, NULL, dst,0, 0, 0, 0, 0, 0,crtc->mode.HDisplay, crtc->mode.VDisplay);crtc->shadowClear = FALSE;}else {while (n--) {BoxRec dst_box;dst_box = *b;dst_box.x1 -= crtc->filter_width >> 1;dst_box.x2 += crtc->filter_width >> 1;dst_box.y1 -= crtc->filter_height >> 1;dst_box.y2 += crtc->filter_height >> 1;pixman_f_transform_bounds(&crtc->f_framebuffer_to_crtc, &dst_box);CompositePicture(PictOpSrc,src, NULL, dst,dst_box.x1, dst_box.y1, 0, 0, dst_box.x1,dst_box.y1, dst_box.x2 - dst_box.x1,dst_box.y2 - dst_box.y1);b++;}}FreePicture(src, None);FreePicture(dst, None);
}

  xf86RotateCrtcRedisplay函数会使用FB Root创建一个源Picture,并设置源的transform和filter属性。使用FB Rotate创建一个目标Picture,最后调用CompositePicture将源融合到目标上去。如果硬件支持这种类型的操作,将会由驱动的Composite函数完成该操作,如果硬件不支持,将会由软件完成。

总结

  • 驱动要支持旋转操作,必须要实现上述的4个xf86CrtcFuncsRec结构体成员函数;
  • 旋转操作实际由源到目标的Composite操作完成,源带transform和filter属性;
  • 旋转操作是持续不断进行的;
  • 如果硬件不支持这种类型的Composite,将会由软件实现,性能影响较大;

Xorg屏幕旋转实现方式相关推荐

  1. iOS 屏幕旋转常用方式

    //此方法在进入应用和当屏幕旋转的额时候,会调用 - (UIInterfaceOrientationMask)application:(UIApplication *)application supp ...

  2. 通过广播获取Android屏幕旋转事件

         Android获取系统屏幕旋转的方式有几种,其中比较常见的是通过重写Activity中的onConfigurationChanged方法,但是这种方法有个缺陷,当测试程序在后台运行的时候不能 ...

  3. ios 旋转屏幕试图切换_总结iOS App开发中控制屏幕旋转的几种方式

    在iOS6之前的版本中,通常使用 shouldAutorotateToInterfaceOrientation 来单独控制某个UIViewController的方向,需要哪个viewControlle ...

  4. iOS传感器:实现一个随屏幕旋转的图片

    作者 非典型技术宅 关注 2017.05.24 17:22* 字数 1568 阅读 351评论 7喜欢 14 在写上一个动画系列的时候学到了非常多的知识,也认识了很多人.例如受邀进入了某个神秘的动效组 ...

  5. Android 设定横屏,禁止屏幕旋转,Activity重置 [更新视频播放器相关]

    1. 设定屏幕方向 当指定了屏幕的方向后(非SCREEN_ORIENTATION_UNSPECIFIED),屏幕就不会自己主动的旋转了 有2中方式控制屏幕方向: 1.1 改动AndroidManife ...

  6. 【Android RTMP】NV21 图像旋转处理 ( 问题描述 | 图像顺时针旋转 90 度方案 | YUV 图像旋转细节 | 手机屏幕旋转方向 )

    文章目录 安卓直播推流专栏博客总结 一. NV21 图像格式与 Camera图像传感器方向问题 二. NV21 图像格式视频旋转 1. 图像旋转问题及解决方案 ( 顺时针旋转 90 度 ) 2. NV ...

  7. Android 屏幕旋转时Activity的变化

    Android开发文档上专门有一小节解释这个问题.简单来说,Activity是负责与用户交互的最主要机制,任何"设置"(Configuration)的改变都可能对Activity的 ...

  8. iOS屏幕旋转 浅析

    一.两种orientation 了解屏幕旋转首先需要区分两种orientation 1.device orientation 设备的物理方向,由类型UIDeviceOrientation表示,当前设备 ...

  9. 怎么设置苹果手机的小圆点_iPhone屏幕旋转怎么设置?关于苹果手机设置的一些小技巧...

    阅读本文前,请您先点击上面的"蓝色字体",再点击"关注",这样您就可以继续免费收到文章了.每天都会有分享,都是免费订阅,请您放心关注. 注:本文转载自网络,不代 ...

  10. IOS6屏幕旋转详解(自动旋转、手动旋转、兼容IOS6之前系统)

    转自 http://blog.csdn.net/zzfsuiye/article/details/8251060 概述: 在iOS6之前的版本中,通常使用 shouldAutorotateToInte ...

最新文章

  1. 快来学习Redis 分布式锁的背后原理
  2. 手把手教你写移动端瀑布流控件布局篇
  3. centos升级python_CentOS 升级Python3
  4. 【AI-1000问】人脸的4个方向,你还分的清楚吗?
  5. 二十四、数据挖掘时序模式
  6. php sqlsrv 分页,Php+SqlServer如何实现分页显示
  7. 逆向so_安卓逆向 | 分析调试与so调用实战
  8. 搞定面试算法系列 | 分治算法三步走
  9. 【今日CV 计算机视觉论文速览】Tue, 12 Mar 2019
  10. c++ 项目_罗纳尔多相信C罗从事技巧类项目,其成就不会亚于他在足坛的成绩
  11. jmeter 跨线程执行变量
  12. 通过掌握谷歌成为更好的程序员
  13. 计算机如何驱动无线网络,笔记本电脑无线网卡驱动怎么安装?
  14. HTML+CSS+JS实现十款好看的登录注册界面模板,赶紧收藏起来吧!
  15. TinyPNG压缩图片的网站
  16. 无法启动此程序 因为计算机中丢失msvcr71.dll,msvcr71.dll丢失怎样修复?计算机中丢失msvcr71.dll的解决方法...
  17. 对于Linux内核tty设备的一点理解 【转】
  18. 【安安教具】-【数学】-【一阶线性齐次方程】模拟器 教你如何用python制作一阶线性齐次方程模拟器 python项目小发明
  19. openwrt procd启动流程和脚本分析
  20. WiFi温湿度传感器开发

热门文章

  1. 李沐动手学深度学习V2-RNN循环神经网络原理
  2. 题目内容: 班级第一次列队,通常老师会让同学按身高排成一列,然后1、2报数,喊到1的同学向前一 步,就这样,队伍就变成两列了。假设现在一个班级有n个同学,并且他们已经按身高排成 了一列,同学按身高从1
  3. 确定部分分式中待定系数的留数方法
  4. vue+环信客服前端对接
  5. 如何在html中加入动图,如何在PS图像中插入动图(gif)?
  6. 潘悟云方言计算机,山东方言精组与见晓组声母的分合研究
  7. java clh_AQS基础——多图详解CLH锁的原理与实现
  8. 电阻电容电感二极管三极管在电路中的作用
  9. 机器学习:考试预测实战(特征隐射,独热编码,特征重要性选择,网格搜索调参)
  10. 学之思开源考试系统 - 数据库设计文档