linux drm 架构 之代码分析

来源:互联网 发布:mac 远程桌面 右键 编辑:程序博客网 时间:2024/05/17 06:35

一 上一篇介绍了 Linux 的显示驱动drm 的架构,在这里按一定顺序回顾一下:

 1 我把显示器连到显卡的DVI输出口, 这个连接抽象成 Connector 

 2    在 DVI 的 Connector 上驱动会分配 DVI 信号的 Encoder ,  如果没分配, connector 资源上会找到 所有可用的 encoders 

 3    encoder 是为图像扫描现场 crtc 服务的, 驱动可能会给encoder 分配crtc , 或者从 encoder 的 possible_crtc 上能找到可用的

 4    crtc 扫描现场要配置显示图像的物理内存区 fb 

 5    fb -> crtc -> encoder - > connector 这种关系绑定之后,绘图工作已经开始, 你可以在fb 上任意写画,然后立马得到显示!

6 然而为了避免图像撕裂,可以建立多 fb (缓冲) 通过 pageFlip 操作来刷新画图。

7 当然还有专为video 刷新用的plane , plane 也要绑定到 crtc  才能工作。 

二 总结 + drm api 的使用:

api 使用参考 David Herrmann <dh.herrmann@googlemail.com> 的 drm-howto 以及 weston 还有 drm自带的 modetest 程序


drm api 核心配置就是要绑定一个 crtc 的关系 fb -> crtc -> encoder - > connector  

我们来看“一”的回顾,咋是按照逆向的顺序?哈哈其实这样才顺理成章, api 如何用,往下看:

1 首先要打开drm 驱动模块,然后获取所有的资源 

fd = open("/dev/dri/card0", O_RDWR | O_CLOEXEC);

drmModeRes res = drmModeGetResources(fd);    

res 里有啥, res 里告诉了有几个connector , 几个 encoder , 几个 crtc 等以及他们的id , 完全不成套!

  2 从 connector 开始, 顺藤摸瓜

先获取 connecotr 的具体资源 

drmModeConnector *  conn = drmModeGetConnector(fd, res->connectors[i]);

conn资源里重要的有两部分,一部分是通过线缆读出来显示器的 "modes " 如 1920x1080@60 等, 当然你要选一个最喜欢的

另一部分是encoder 按照一章节的2顺序开始找 encoder (看 drmModeConnector 的定义)  :p

3 给encoder 寻找合适的 crtc 

按照一章节的 3 顺序找 crtc 

4 为 crtc 创建fb 

 drm 的例子 modetest 写的很详细,  ARGB  可以直接 drmModeAddFB , 多平面的fb 可以用 drmModeAddFB2 

5 绑定

核心四元组 < fb , crtc , conn ,  mode >


  int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId,

               uint32_t x, uint32_t y, uint32_t *connectors, int count,

             drmModeModeInfoPtr mode);


6 pageFlip 

  extern int drmModePageFlip(int fd, uint32_t crtc_id, uint32_t fb_id,
                 uint32_t flags, void *user_data);
  

 这个的玩法得好好记下, 

首先 poll (drm_fd ) 可以收到 drm 的 POLLIN  消息, 消息里面无非两种一种是 VBLANK , 一种是 pageFlip complete 

其次 收到 消息后必须要 调用drmHandleEvent(drm_fd , &evctx); 来处理消息 ,记得必须把你的 pageFlip 处理函数填到evctx里, 

pageFlip 处理函数里干啥呢, pageFlip 一帧结束了,当然要 pageFlip 下一帧!


     7 plane 

plane 的玩法没搞明白,尝试了下,使用多缓冲 调 drmModeSetPlane 来换页可以实现视频的播放,但遇到两个问题:

其一是 SetPlane 的时机, 如何等待一个显示器的场同步? 看了 vblank 的code 感觉 vblank 是针对一个显卡的同步,但我有多个显示器呢?

其二是SetPlane 的运行耗时,我的 i3 cpu 执行一次用了 22 ~ 23 ms , 莫名其妙。

本想着plane 的yuv 通道可以节省资源,有这两大问题在就没法办了, pageFlip 的 fb 只能跟显示器相同颜色空间,并且通常是 ARGB !!

原创粉丝点击