libdrm库封装了DRM driver提供的这些接口。通过libdrm库,程序可以间接调用DRM Driver。
DRM驱动会在/dev/dri下创建3个设备节点:
使用drmOpen()打开设备。它根据指定的name和busid,在上述三个设备中选择匹配的节点。
也可以使用open(),直接打开指定设备。
得到、设置capability。
下图显示各个组件,以及组件之间的关联关系。在DRM的函数名中称作资源(Resource)。如drmModeGetResources()。
每种资源的结构都定义了一个成员,唯一标识这个资源。如drmModeCrtc的crtc_id、drmModeConnector的connector_id、drmModeEncoder的encoder_id、drmModePlane的plane_id。
显示设备的设置、状态,保存在若干结构、变量中,如下图。如drmModeModeInfo,保存设备大小,刷新率。drmModeConnection保存连接状态。
drmModeRes结构保存DRM设备的资源集。
drmModeRes的成员fbs、crtcs、connectors、encoders是变长数组,数组长度保存在对应的变量,如count_fbs中。数组中保存的是资源ID。
函数drmModeGetResources()用于得到资源集。
根据资源 ID 得到对应的资源,包括connector、encoder、crtc。
与其他资源不同,plane资源不在drmModeRes结构中,而是保存在drmModePlaneRes结构。
成员planes是变长数组,数组长度保存在count_planes中。这里保存是plane的资源ID。
drmModeGetPlaneResources()得到plane资源集。
drmModeGetPlane() 根据Plane ID得到Plane。
drmModeProperty结构保存属性。
drmModeObjectProperties保存资源的属性集。
drmModeObjectGetProperties()得到资源属性集。
drmModeGetProperty()得到属性,drmModeObjectSetProperty()设置属性。
使用drmIoctl()创建、映射framebuffer。
使用Linux API函数 mmap(),将framebuffer映射到用户空间。
加入framebuffer(不是提交显示!)。
drmModeAtomicReq保存DRM请求。
drmModeAtomicCommit()提交请求。比如,将framebuffer保存的图像提交显示。
将framebuffer绑定到plane。程序更新framebuffer,就是更新plane。
Linux DRM API - NVIDIA
DRM示例工程 zizimumu/DRM_test
如下是DRM Driver 所依赖的 Component Framework。
framebuffer是驱动和应用层都能访问的一块内存区域。
可以把它理解为一块画布。画画之前需要将它格式化,指定是画油画,还是国画(色彩模式,比如 RGB24,YUV 等),画布需要多大(分辨率)。
直译为阴极摄像管上下文。它读取当前扫描缓冲区的像素数据,借助于PLL电路,生成视频模式定时信号。
简单来说,它就是显示输出的上下文,对内连接 Framebuffer ,对外连接 Encoder。
可以把它理解为扫描仪。它扫描画布(framebuffer)上的内容,叠加 planes 的内容,传给 encoder。
直译为 编码器。它将内存的像素编码转换为显示器所需要的信号。
可以想象成,它将你的画在不同类型、型号的显示设备上显示,将其转换成不同的电信号,比如 DVID、VGA、YPbPr、CVBS、Mipi、eDP 等。
直译为 连接器。它常常对应于物理连接器 (VGA、DVI、FPD-Link、HDMI、DisplayPort、S-Video …) ,连接到一个显示输出设备 (monitor、laptop panel …) 。
与输出设备相关的信息(如连接状态、EDID数据、DPMS状态或支持的视频模式),也存储在 Connector 内。
直译为 平面。Plane和 framebuffer 一样是内存地址。
它的作用是干什么呢?想象这样一个场景,笔者正在很不专心地一边看动作大片,一边写文章。动作大片每一帧的变化都很大,需要全幅更新。写文章则可能半天挤不出一个字,基本上不需要更新。这是显卡使用的两个极端。一个是全幅高速更新的 Video Mode,一个是文字交互这种小范围更新的 Graphics Mode。此时轮到 Planes 出马,它给 Video 刷新提供了高速通道,使 Video 单独为一个图层,可以叠加在 Graphic 上面或下面,并具有缩放等功能。
Planes可以有多个。最后扫描仪(CRTC)扫描的画,实际上是framebuffer 和 若干planes 的组合(Blending)。
厂商可能会对planes的类型、用途做出规范。比如,
DRM_PLANE_TYPE_PRIMARY: 一定要有,由于显示背景或者图像内容
DRM_PLANE_TYPE_OVERLAY: 用于显示Overlay
DRM_PLANE_TYPE_CURSOR: 用于显示鼠标
Linux DRM(二)基本概念和特性
Display中的DRM模块介绍
DRM/KMS 基本组件介绍
DRM 是目前主流的图形显示框架,Linux 内核中已经有Framebuffer 驱动用于管理显示设备的 Framebuffer, Framebuffer 框架也可以实现Linux 系统的显示功能,但是缺点如下:
下面是Linux graphic system 的框架,基于Wayland的Windowing system,在DRI框架下,通过两条路径(DRM和KMS),分别实现Rendering和送显两个显示步骤,注意观察 DRM 框架在其中的作用
DRM 框架的基本流程框图如下:
软件角度框图:
DRM框架涉及到的元素很多,大致如下:
KMS: CRTC,ENCODER,CONNECTOR,PLANE,FB,VBLANK,property
GEM: DUMB、PRIME、Fence
下面一一介绍
libdrm:
应用层的一个动态链接库,对底层接口进行封装,向上层提供通用的API接口,主要是对各种IOCTL接口进行封装。
KMS:
Kernel mode setting 简而言之做两件事:更新画面 + 设置显示参数
更新画面: 显示buffer 的切换,多图层之间的合成方式,每个图层的显示位置
设置显示参数:包含 刷新率,分辨率,电源状态 休眠唤醒等等。
GEM:
Graphic Execution Manager,主要负责显示buffer的分配和释放,也是GPU唯一用到DRM的地方。
学习 drm 就是学习上面这些概念的用法和实现。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)