<!-- /* Font Definitions */ @font-face {font-family:宋体; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-alt:SimSun; mso-font-charset:134; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 135135232 16 0 262145 0;} @font-face {font-family:黑体; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-alt:SimHei; mso-font-charset:134; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:1 135135232 16 0 262144 0;} @font-face {font-family:"/@宋体"; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-charset:134; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 135135232 16 0 262145 0;} @font-face {font-family:"/@黑体"; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-charset:134; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:1 135135232 16 0 262144 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; text-align:justify; text-justify:inter-ideograph; mso-pagination:none; font-size:10.5pt; mso-bidi-font-size:12.0pt; font-family:"Times New Roman"; mso-fareast-font-family:宋体; mso-font-kerning:1.0pt;} h1 {mso-style-next:正文; margin-top:17.0pt; margin-right:0cm; margin-bottom:16.5pt; margin-left:0cm; text-align:justify; text-justify:inter-ideograph; line-height:240%; mso-pagination:lines-together; page-break-after:avoid; mso-outline-level:1; font-size:22.0pt; font-family:"Times New Roman"; mso-font-kerning:22.0pt;} h2 {mso-style-next:正文; margin-top:13.0pt; margin-right:0cm; margin-bottom:13.0pt; margin-left:0cm; text-align:justify; text-justify:inter-ideograph; line-height:173%; mso-pagination:lines-together; page-break-after:avoid; mso-outline-level:2; font-size:16.0pt; font-family:Arial; mso-fareast-font-family:黑体; mso-bidi-font-family:"Times New Roman"; mso-font-kerning:1.0pt;} /* Page Definitions */ @page {mso-page-border-surround-header:no; mso-page-border-surround-footer:no;} @page Section1 {size:595.3pt 841.9pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:42.55pt; mso-footer-margin:49.6pt; mso-paper-source:0; layout-grid:15.6pt;} div.Section1 {page:Section1;} /* List Definitions */ @list l0 {mso-list-id:489178463; mso-list-type:hybrid; mso-list-template-ids:-1904288614 338594570 67698713 67698715 67698703 67698713 67698715 67698703 67698713 67698715;} @list l0:level1 {mso-level-text:%1,; mso-level-tab-stop:39.0pt; mso-level-number-position:left; margin-left:39.0pt; text-indent:-18.0pt;} @list l1 {mso-list-id:734666112; mso-list-type:hybrid; mso-list-template-ids:-1866804122 1008655198 248933464 67698715 67698703 67698713 67698715 67698703 67698713 67698715;} @list l1:level1 {mso-level-text:%1,; mso-level-tab-stop:18.0pt; mso-level-number-position:left; margin-left:18.0pt; text-indent:-18.0pt;} @list l1:level2 {mso-level-number-format:alpha-lower; mso-level-text:"%2/)"; mso-level-tab-stop:39.0pt; mso-level-number-position:left; margin-left:39.0pt; text-indent:-18.0pt;} @list l2 {mso-list-id:1088306772; mso-list-type:hybrid; mso-list-template-ids:557996062 2070169818 67698713 67698715 67698703 67698713 67698715 67698703 67698713 67698715;} @list l2:level1 {mso-level-text:%1,; mso-level-tab-stop:39.0pt; mso-level-number-position:left; margin-left:39.0pt; text-indent:-18.0pt;} @list l3 {mso-list-id:1767262004; mso-list-type:hybrid; mso-list-template-ids:-2076174484 968550278 67698713 67698715 67698703 67698713 67698715 67698703 67698713 67698715;} @list l3:level1 {mso-level-text:%1,; mso-level-tab-stop:60.0pt; mso-level-number-position:left; margin-left:60.0pt; text-indent:-18.0pt;} ol {margin-bottom:0cm;} ul {margin-bottom:0cm;} -->
Marvel Pxa310 graphics 层横屏竖屏切换
Video 的切换做完后,又开始了 graphics 层的旋转,也就是 X server 的旋转,它和 video 层并没有多大区别,差别就在于 x server 是 RGB 的数据,而 video 层是 YUV 的,另外一方面 x server 的架构要远复杂于 mplayer 的架构;
1, Marvel 的 pxa310 没有自己的 DSP 不过有一个图形加速,也就是 M2D ,这玩意的意思就是 memory to device ,实际上,多数用法都是从内存的一个地方按照一定的算法移动到 framebuffer 或者一个中间的内存,所以旋转的操作就交给 M2D 了;
2, 寻找一个合适的地方进行初始化,比如 M2D 内存的分配,数据结构的初始化等等;
3, 寻找一个合适的地方进行旋转的操作;
1, 理解 X server 的架构;
它的架构非常的复杂,我准备专门讨论,这里只是简单的介绍一下,我们用的 xserver 是基于 Kdrive 的,而 kdrive 下面的设备依赖层是由 omap 目录来提供相应的接口实现的,名字是源于 Nokia ,但是实际上的设备是 marvel 的 pxa310 。
简单的说作为 kdrive 的 driver 必须要实现下面的结构体里面的函数指针:
KdCardFuncs omap_funcs = {
.cardinit = omap_card_init,
.cardfini = omap_card_fini,
.scrinit = omap_screen_init,
.scrfini = omap_screen_fini,
.initScreen = omap_init_screen,
.finishInitScreen = omap_finish_init_screen,
.createRes = omap_create_resources,
.dpms = omap_dpms,
};
omap_screen_init 的目的就是要初始化 KdScreenInfo 这个数据结构,并提供给设备独立层使用;而 screen 层本身的实现要依赖于不同的 fb 层,所以它需要调用 omap_plane_enable 来进行层本身的初始化;因为 gcu 本身的操作是针对特定的层的,所以我决定就把 gcu 的初始化放在这里了,这里重要的是源和目的 buffer 的分配,目的肯定是 fb0 的地址,而源的话是通过 m2d 分配的连续地址空间,并虚拟成 xserver 所要的 screen 的 memory_base 。这样对 xserver 来说它所有的操作都是针对这个虚假的 framebuffer ,然后我再适当的时候再把这个内容旋转到真正的 framebuffer 就可以了,相关代码如下:
gcu->format = FORMAT_RGB;
gcu->src_buf[0] = m2d_alloc_buffer(gcu->context, gcu->src_width[0], gcu->src_height[0], GCU_PXLFMT_RGB565);
gcu->dst_buf[0] = m2d_create_buffer(gcu->context, gcu->dst_width[0], gcu->dst_height[0], GCU_PXLFMT_RGB565, plane_info->fb);
这三行代码提供了一些信息给驱动:
1, 数据的格式是 RGB 的而不是 YUV 的;
2, 源数据的格式为 RGB565 的;
3, 目的地的数据格式也是 RGB565 的;
4, 源的数据几何形状为 800X480 的;
5, 目的地的几何形状为 480X800 的;
2, 理解 omap_plane_flush 相关函数;
这个函数的作用其实是需要在 LCD 本身有帧缓存的情况要才有用的,所以对于我们的平台这个函数基本没有用;但这里被我选来作为旋转的地方;
它的调用逻辑如下:
3, 新的输出实现;
剩下的就和 video 的旋转没有多大的区别了:
1, 设置操作源和目的地;
m2d_set_srcbuf0(gcu->context, gcu->src_buf[0]);
m2d_set_dstbuf2(gcu->context, gcu->dst_buf[0]);
2, 取得操作子 ;
SET_OP_REGION_SRC0(&opr[0][0], 0, 0, 0, 0, src_width[0]/2, src_height[0]);
SET_OP_REGION_SRC0(&opr[0][1], src_width[0]/2, 0, 0, dst_height[0]/2, src_width[0]/2, src_height[0]);
这里的 src_width[0] 就是 800 , src_height[0]=480,dst_height[0]=800,dst_width[0]=480;
其实也就是定义了两个矩形,一个是,
起点 0 , 0 ;目的地 0 , 0 ;宽高: 400 , 480 ;
第二个是:
起点 400,0 ;目的地 0,400 ;宽高: 400 , 480 ;
每次旋转一半,分两次旋转;
3, 调用 M2D 提供的操作函数
m2d_rotate_blt(gcu->context, &gcu->opr[0][0], gcu->rotate_degree);
m2d_rotate_blt(gcu->context, &gcu->opr[0][1], gcu->rotate_degree);
这里需要设置旋转度数,为 1 , 2 , 3 ,当然我觉得多半是 1 或者 3 吧。
m2d_submit(gcu->context);
经过这个函数后操作命令已经被放到了环形命令区,等待硬件的操作;
主要的难点就是如何填这些参数,特别是旋转的宽度和高度在大于 497 的时候的设置;
另外的难点在于,驱动提供的接口必须要提供成 800X480 的假象,这样才不会导致 xserver 在它的 framebuffer 管理里面把图像布局成 480X800 的;另外这个旋转的动作是不能告诉其它客户端程序的,比如 matchbox ,否则布局都会搞错;
还有一个地方需要注意就是:
plane_info->fix.line_length = 1600;
否则 xserver 的布局也会出错,因为驱动传上来的值有可能是 480X2 的,如果是这样就需要强制设成 800X2 ;
1, 屏幕漆黑一片,怎么回事?
从本质上说是没有把数据写到 framebuffer ;那么出现这个原因就可能是旋转的参数设置错误,也有可能是源和目的地设置错误;
2 ,屏幕出现了内容但是显得很小,还有很多地方重叠;
这个可能是 xserver 的布局从问题导致的;可以通过一个简单的测试证明:
找一个 800X480 的图片直接 cat 到 fb0 ,如果结果是正确的现实,那么说明 LCD 本身就是 800X480 的;如果出现正确显示了图片,但是每一行的后半部分不见了,那么就说明 LCD 是 480X800 的,但是驱动把行同步设置成了 800 ;如果结果是图像都有重叠,也就是一行的后半部分出现在了下一行,这样的话,说明驱动是正确的,只是源数据出错了,也就是 xserver 布局错了,很有可能是 line_length 设置错误的结果;
如有其它疑问请参阅 video 横屏竖屏切换 .doc
作者: wylhistory;
联系方式: [email protected]