Linux DRM modesetting API分析

前言

本文阅读总结自David Rheinsberg的drm-howto代码,代码的编排非常用心。注释也写的相当详尽,是很好的DRM应用程序入门参考资料

modeset.c

1、打开/dev/dri/card0节点
检查支持DRM_CAP_DUMB_BUFFER:drmGetCap(fd, DRM_CAP_DUMB_BUFFER, &has_dumb)

2、查找可用的display设备,即connector+crtc+framebuffer组合
获取drmModeRes,该结构包含所有需要的信息:drmModeGetResources(fd);
获取drmModeConnector:conn = drmModeGetConnector(fd, res->connectors[i])
检查该Connector是否没有使用,即没有panel连接上
直接使用第一个mode(分辨率刷新率):memcpy(&dev->mode, &conn->modes[0], sizeof(dev->mode))
查找一个CRTC,在获得CRTC之前需要先获取Encoders:enc = drmModeGetEncoder(fd, conn->encoder_id)
crtc = enc->crtc_id

3、创建一个framebuffer
创建一个dumb buffer:drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &creq)
创建一个framebuffer实例:drmModeAddFB(fd, dev->width, dev->height, 24, 32, dev->stride,dev->handle, &dev->fb);
准备dumb buffer映射:drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &mreq)
进行实际的mmap内存映射:dev->map = mmap(0, dev->size, PROT_READ | PROT_WRITE, MAP_SHARED,
fd, mreq.offset);
将framebuffer置0黑色:memset(dev->map, 0, dev->size);

4、准备好以上对象后,就可以编程使CRTC连接到framebuffer和connector的组合:drmModeSetCrtc(fd, iter->crtc, iter->fb, 0, 0,
&iter->conn, 1, &iter->mode);

5、后面需要修改屏幕显示内容时,只需要修改framebuffer的内容即可

modeset-double-buffered.c

1、如果只有一个framebuffer,当我们向front buffer写入更新画面写入一半时,这个时候如果CTRC开始扫描输出下一帧,可能就会看到flickering

2、double-buffered就是申请两块framebuffer,front buffer用于当前的显示buffer,每次写入都更新back-buffer,然后调用drmModeSetCrtc(fd, iter->crtc, buf->fb, 0, 0, &iter->conn, 1, &iter->mode)交换front buffer和back-buffer

modeset-vsync.c

1、vertical-blank是CRTC扫描显示一帧framebuffer和下一帧画面之间的时间

2、drmModePageFlip():调度一个buffer-flip为下一个vblank事件,然后通知我们。它需要一个CRTC-id, fb-id和data-pointer做参数然后调度page-flip。这是完全异步的并且立即返回

3、drmHandleEvent():当page-flip发生时,DRM-fd就会变成可读的,然后我们就可以调用drmHandleEvent(),这个接口会读所有的vblank/page-flip 事件,然后调用modeset_page_flip_event()回调函数

4、modeset_page_flip_event():回调函数,函数里面重新更新了framebuffer,然后调用drmModePageFlip()调度一个page-flip为下次vsync

5、drmModePageFlip(fd, dev->crtc, buf->fb, DRM_MODE_PAGE_FLIP_EVENT, dev);
如果调用drmModePageFlip之后马上又调用一遍,将会返回EBUSY如果page-flip还没有发生。所有总是会传递DRM_MODE_PAGE_FLIP_EVENT,当page-flip发生了能够得到通知以便可以开始渲染下一帧

modeset-atomic.c

1、Plane:硬件图层,用于合成和叠加图像。三种类型:primary, cursor and overlay
一个Plane用法的例子:想象一个静态的电脑桌面,只有鼠标光标在移动,这个时候就不需要每次移动光标时都计算整个画面,我们可以只更新cursor plane然后硬件会自动将其叠加到primary plane

2、设计到多图层时会有同步问题,KMS API不是原子的,所有你要更新primary plane和overlay planes用不同的IOCTLS,这会导致tearing和blocking等问题。atomic API可以解决这种问题

3、drmModeAtomicCommit():所有的plane可以在一个IOCTL里更新,这可以是异步的,也可以是完全阻塞的

4、Property:由3部分组成:name、id、value。id是该property在DRM框架中全局唯一的标识符。操作property:通过name来获取property,通过id来操作property,通过value来修改property的值,完成这些操作的接口,就是atomic接口

5、drmSetClientCap(fd, DRM_CLIENT_CAP_ATOMIC, 1):被DRM_MODE_PROP_ATOMIC修饰过的property,只有应用程序支持Atomic操作是才可见,因此需要设置DRM_CLIENT_CAP_ATOMIC这个flag,告诉DRM驱动该应用程序支持Atomic操作

6、Property操作步骤:1.drmModeGetProperty()来获取property的相关信息 2.drmModeAtomicAddProperty()来修改property的值 3.drmModeAtomicCommit()发起真正的修改请求

7、获取connector属性:props = drmModeObjectGetProperties(fd, conn_id, DRM_MODE_OBJECT_CONNECTOR);
property_crtc_id = get_property_id(fd, props, “CRTC_ID”);

8、获取crtc属性:props = drmModeObjectGetProperties(fd, crtc_id, DRM_MODE_OBJECT_CRTC);
property_active = get_property_id(fd, props, “ACTIVE”);
property_mode_id = get_property_id(fd, props, “MODE_ID”);

9、开始modesetting:req = drmModeAtomicAlloc();
drmModeAtomicAddProperty(req, crtc_id, property_active, 1);
drmModeAtomicAddProperty(req, crtc_id, property_mode_id, blob_id);
drmModeAtomicAddProperty(req, conn_id, property_crtc_id, crtc_id);
drmModeAtomicCommit(fd, req, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
以上代码并没有对fb_id的操作,所以作用只是初始CRTC、ENCODER、CONNECTOR硬件以及建立硬件链路关系,并不会显示framebuffer的内容

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux DRM(Direct Rendering Manager)驱动是Linux操作系统中用于显卡和显示设备管理的驱动程序。它提供了一套统一的接口,使得用户可以通过应用程序直接访问显卡硬件,实现图形渲染和硬件加速等功能。 Linux DRM驱动包括了核心驱动模块和设备驱动模块。核心驱动模块负责提供基本的显卡管理功能,如内存分配、模式设置和渲染命令队列等。设备驱动模块负责支持特定显卡和显示设备的硬件特性和功能。通过这种模块化的设计,Linux DRM驱动能够支持多种显卡和显示设备。 在分析Linux DRM驱动时,可以从以下几个方面入手: 1. 驱动架构:了解Linux DRM驱动的整体架构,包括核心驱动模块和设备驱动模块的功能和交互方式。 2. 设备支持:分析特定显卡和显示设备的驱动模块,了解其支持的硬件特性和功能。 3. 内存管理:了解Linux DRM驱动中的内存管理机制,包括内存分配、显存管理和页面交换等。 4. 渲染和硬件加速:分析Linux DRM驱动中的渲染命令队列和硬件加速功能的实现方式。 5. 显示管道:了解Linux DRM驱动中的显示管道管理机制,包括模式设置和输出控制等。 通过对Linux DRM驱动的分析,可以更深入地理解显卡和显示设备的工作原理,为开发应用程序和调优系统性能提供指导和参考。此外,还可以通过分析和改进Linux DRM驱动来实现新的显卡和显示设备的支持,提升系统的兼容性和性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值