17. 屏幕显示(DRM)介绍

17.1. 前言

本章节基于 《DRM(Direct Rendering Manager)》 进行DRM的应用开发的讲解, 该专栏还具有GPU,DRM驱动开发等图形学的相关教程及理论分析。

17.2. DRM介绍

DRM是Linux目前主流的图形显示框架,相比FB架构,DRM更能适应当前日益更新的显示硬件。 比如FB原生不支持多层合成,不支持VSYNC,不支持DMA-BUF,不支持异步更新,不支持fence机制等等, 而这些功能DRM原生都支持。同时DRM可以统一管理GPU和Display驱动,使得软件架构更为统一,方便管理和维护。

未找到图片

可以看到DRM的图像系统可以分为两部分

  • 应用层– libdrm

  • 内核驱动层— GEM, KMS

libdrm: 对底层接口进行封装,向上层提供通用的API接口,主要是对各种IOCTL接口进行封装。

KMS(Kernel Mode Setting): 即Mode setting:更新画面和设置显示参数。

  1. 更新画面:显示buffer的切换,多图层的合成方式,以及每个图层的显示位置。

  2. 设置显示参数:包括分辨率、刷新率、电源状态(休眠唤醒)等。

GEM(Graphic Execution Manager): 主要负责显示buffer的分配和释放,内存管理与同步。

17.3. DRM显示

本小节主要引用下列文章进行讲解 《drm-kms.pdf》

17.3.1. DRM与framebuffer的区别

未找到图片
  • framebuffer的使用十分简单,只需要在用户空间定义一个framebuffer的内存空间, 只要直接操作这块内存就可以轻易的改变屏幕的显示

  • 对于DRM而言,在framebuffer与显示器之间有四个部件, framebuffer的数据经过几个部件的联合处理最终把图像输出到显示器中

除此之外,framebuffer相比DRM而言有更多的劣势

  1. DRM具有更多的社区维护者

  2. DRM为显示提供更多的设置

  3. DRM在用户空间能够享受更广泛的运用

不过framebuffer在图像并不复杂的场景下的开发难度更优于DRM显示系统

17.3.2. DRM显示系统分析

未找到图片

让我们分析一下绿框中的五个部件,以及他们的联动

17.3.2.1. DRM Framebuffer

与上一章节的framebuffer一样,是一片存放图像的内存区域, 需要设置图像的格式(RGB888,YUV,C8等)以及画布的大小

17.3.2.2. CRTC

CRTC的名字来源于Cathode Ray Tube Controller,中文名为阴极射线显像管控制器

世界上第一台彩色电视正是CRT显示器, 取这个名字的主要原因这个部件很像阴极射线显像管控制器, 电子枪打出的电子撞击到屏幕上的荧光物质使其发光。只要控制电子枪从左到右扫完一行(也就是扫描一行),然后 从上到下扫描完所有行,这样一帧图像就显示出来了。也就是说,显示一帧图像电子枪是按照 ‘Z’形在运动,当扫描速度很快的时候看起来就是一幅完成的画面了。

在DRM显示系统中CRTC会配置display timings和显示分辨率(Planes提供)来扫描framebuffer上的内容,传给Encoder。

display timings: 扫描framebuffer的时序,因为LCD屏的显示并不像0.96寸的屏幕那样, 直接把所有的显示数据写进去就可以显示东西,LCD屏需要一定的时序才能正确显示东西, 因此,CRTC在这里就有很重要的作用,生成视频模式定时信号,输出内容到Encoder中,Encoder和Connector则只作为数据的转换和传输

关于LCD屏幕时序,下面这篇文章有详细介绍 《LCD基础概念(一):LCD timing 时序参数总结》

17.3.2.3. Planes

普遍翻译为平面,我觉得译为图层更合适,Planes是一个包含向CRTC发送数据的缓存块的内存对象, 每个CRTC必须关联一个Planes,它是CRTC决定采用哪种视频模式的根据—显示分辨率(宽度和高度),像素大小,像素格式,刷新率等

Planes会分为三种类型:

  1. DRM_PLANE_TYPE_PRIMARY: 主要图层,显示背景或者图像内容,每个CRTC中含一个

  2. DRM_PLANE_TYPE_OVERLAY: 用于显示叠加、缩放,每个CRTC中含一个以上

  3. DRM_PLANE_TYPE_CURSOR: 用于显示鼠标,每个CRTC中含0-N个

通常驱动会把framebuffer绑定到 DRM_PLANE_TYPE_PRIMARY 上。

LubanCat-RK系列板卡图层包含三个,一个 DRM_PLANE_TYPE_PRIMARY 和两个 DRM_PLANE_TYPE_OVERLAY (其中一个无法正常使用)

Planes叠加的现象如下

未找到图片

17.3.2.4. Encoder

译为编码器。它的作用就是将 pixel 像素编码(转换)为显示器所需要的信号。

如果我们要把图像输出到不同的显示器上显示,需要将其转化为不同的电信号,比如 DVID、VGA、YPbPr、CVBS、Mipi、eDP 等。

所以它的作用:负责将帧转换为适当的格式,通过连接器传输。

比如说:HDMI connector 需要使用TMDS格式的数据才能驱动,因此需要一个能够把像素格式转换为TMDS的编码器。

17.3.2.5. Connector

译为连接器。Connector 常常对应于物理连接器 (VGA, DVI, FPD-Link, HDMI, DisplayPort, S-Video …) 他会连接将一个物理显示输出设备 (monitor, laptop panel, …) 。 与当前物理连接的输出设备相关的信息(如连接状态,EDID数据,DPMS状态或支持的视频模式)也存储在 Connector 内。

17.3.2.6. 总结

到此,你就会发现DRM显示框架并不是十分复杂,理解之后就会对显示框架有大概的了解, 通过后面的DRM应用编程后,我们对它的理解会更深。

17.3.2.7. 查看drm的相关信息

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#安装测试工具
sudo apt install libdrm-tests

    #运行测试
modetest

    root@lubancat:~# modetest
    trying to open device 'i915'...failed
    trying to open device 'amdgpu'...failed
    trying to open device 'radeon'...failed
    trying to open device 'nouveau'...failed
    trying to open device 'vmwgfx'...failed
    trying to open device 'omapdrm'...failed
    trying to open device 'exynos'...failed
    trying to open device 'tilcdc'...failed
    trying to open device 'msm'...failed
    trying to open device 'sti'...failed
    trying to open device 'tegra'...failed
    trying to open device 'imx-drm'...done
    Encoders:
    id      crtc    type    possible crtcs  possible clones
    34      33      DSI     0x00000001      0xffffffff

    Connectors:
    id      encoder status          name            size (mm)       modes   encoders
    35      34      connected       DSI-1           68x110          1       34
    modes:
                    index name refresh (Hz) hdisp hss hse htot vdisp vss vse vtot
    #0 720x1280 60.22 720 730 750 780 1280 1290 1300 1320 62000 flags: ; type: preferred, driver
    props:
                    1 EDID:
                                    flags: immutable blob
                                    blobs:

                                    value:
                    2 DPMS:
                                    flags: enum
                                    enums: On=0 Standby=1 Suspend=2 Off=3
                                    value: 0
                    5 link-status:
                                    flags: enum
                                    enums: Good=0 Bad=1
                                    value: 0
                    6 non-desktop:
                                    flags: immutable range
                                    values: 0 1
                                    value: 0
                    4 TILE:
                                    flags: immutable blob
                                    blobs:

                                    value:

    CRTCs:
    id      fb      pos     size
    33      36      (0,0)   (720x1280)
    #0 720x1280 60.22 720 730 750 780 1280 1290 1300 1320 62000 flags: ; type: preferred, driver
    props:
                    24 VRR_ENABLED:
                                    flags: range
                                    values: 0 1
                                    value: 0

    Planes:
    id      crtc    fb      CRTC x,y        x,y     gamma size      possible crtcs
    31      33      36      0,0             0,0     0               0x00000001
    formats: XR24 AR24 RG16 XB24 AB24 RX24 RA24 AR15 XR15 AB15 XB15 BG16
    props:
                    8 type:
                                    flags: immutable enum
                                    enums: Overlay=0 Primary=1 Cursor=2
                                    value: 1
                    32 zpos:
                                    flags: immutable range
                                    values: 0 0
                                    value: 0

    Frame buffers:
    id      size    pitch

    root@lubancat:~#

可以看到CRTC Planes Connectors都有列举,省略的部分包含部分绑定信息,可以查看源码分析