linux drm 架构 之代码分析

2019-07-13 09:12发布

一 上一篇介绍了 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 的 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 只能跟显示器相同颜 {MOD}空间,并且通常是 ARGB !!