• 了解libdrm 应用层代码库

1.Graphics Framework

在这里插入图片描述

2.Introduction to libdrm

  libdrm provides a user space library for accessing the DRM, direct rendering manager, on operating systems that support the ioctl interface. libdrm is a low-level library, typically used by graphics drivers such as the Mesa DRI drivers, the X drivers, libva and similar projects.

2.1.libdrm framework

  DRM是Linux内核层的显示驱动框架,它把显示功能封装成 open/close/ioctl 等标准接口,用户空间的程序调用这些接口,驱动设备,显示数据。

  libdrm库封装了DRM driver提供的这些接口。通过libdrm库,程序可以间接调用DRM Driver。

在这里插入图片描述

  DRM exports API through ioctl, libdrm is a user mode library to wrap these ioctls, please reference xf86drm.h in libdrm for detailed explanation. The general steps to use the libdrm are:

  • open/drmOpen /dev/dri/cardN device node
  • call drmModeGetResources, get all the drmModeRes resources. Resources include all the fb, crtc, encoder, connector, etc.
  • loop through drmModeRes structure, call drmModeGetConnector, get the first connected connector(DRM_MODE_CONNECTED)
  • drmModeConnector stores all the supporting mode, choose one from them.
  • loop through drmModeRes,call drmModeGetEncoder. If the encoder matches with the selected mode, save the drmModeModeInfo for later use.
  • create kms_driver, create buffer object,get the pitch of the BO,and map the BO to user space.
  • draw on the BO using cairo or whatever graphic toolbox you like.
  • get original display mode by calling drmModeGetCrtc, this will be used after program exit to restore the original mode.
  • get frame buffer ID by calling drmModeAddFB, whose argument is BO handle.
  • call drmModeSetCrtc with frame buffer ID, the BO attached with the FB is outputed to display.

2.libdrm编译

2.1.libdrm-1.0.0代码下载:

  • https://dri.freedesktop.org/libdrm/

编译:

./configure
make -j8

编译报错:

xf86drm.c:66:12: fatal error: X11/Xlibint.h: No such file or directory
 #  include <X11/Xlibint.h>
            ^~~~~~~~~~~~~~

解决:sudo apt install libx11-dev

安装:

sudo make install

uos@uos-PC:/usr/local/lib$ ls -l
总用量 420
-rw-r--r-- 1 root staff 254476 129 17:24 libdrm.a
-rwxr-xr-x 1 root staff    783 129 17:24 libdrm.la
lrwxrwxrwx 1 root staff     15 129 17:24 libdrm.so -> libdrm.so.1.0.0
lrwxrwxrwx 1 root staff     15 129 17:24 libdrm.so.1 -> libdrm.so.1.0.0
-rwxr-xr-x 1 root staff 154248 129 17:24 libdrm.so.1.0.0
drwxr-sr-x 2 root staff   4096 129 17:24 pkgconfig
drwxrwsr-x 4 root staff   4096 112 17:09 python2.7
drwxrwsr-x 3 root staff   4096 112 17:09 python3.7

2.2.libdrm 源码编译:

 17 Compiling
 18 ---------
 19 
 20 To set up meson:
 21 
 22     meson builddir/
 23 
 24 By default this will install into /usr/local, you can change your prefix
 25 with --prefix=/usr (or `meson configure builddir/ -Dprefix=/usr` after
 26 the initial meson setup).
 27 
 28 Then use ninja to build and install:
 29 
 30     ninja -C builddir/ install
 31 
 32 If you are installing into a system location you will need to run install
 33 separately, and as root.

编译安装命令:

sudo apt install meson
meson builddir/ --prefix=/home/work/libdrm_install
sudo ninja -C builddir/ install

3.APIs

  DRM驱动会在/dev/dri下创建设备节点:

root@uos-PC:/dev/dri# ls -l
总用量 0
drwxr-xr-x  2 root root         80 129 17:01 by-path
crw-rw----+ 1 root video  226,   0 129 17:01 card0
crw-rw----+ 1 root render 226, 128 129 17:01 renderD128

3.1.drmOpen()

drmOpen
  ->drmOpenByBusid
    ->fd = drmOpenMinor(i, 1); //dev/dri/card*

  Looks up the specified name and bus ID, and opens the device found. The entry in /dev/dri is created if necessary and if called by root.

  550 int drmOpen(const char *name, const char *busid)
   551 {
   552 #ifdef XFree86Server
   553     if (!drmAvailable() && name != NULL) {
   554     /* try to load the kernel */
   555     if (!xf86LoadKernelModule(name)) {
   556         ErrorF("[drm] failed to load kernel module \"%s\"\n",
   557                name);
   558         return -1;
   559     }
   560     }
   561 #endif
   562     
   563     if (busid) {
   564     int fd;
   565     
   566     fd = drmOpenByBusid(busid);                                                                                                                                                                                                       
   567     if (fd >= 0)
   568         return fd;
   569     }   
   570     if (name)
   571     return drmOpenByName(name); 
   572     return -1;
   573 } 

3.2.drmModeGetResources

  retrieve current display configuration information.

  drmModeGetResources allocates, populates, and returns a drmModeRes structure containing information about the current display configuration. The structure contains the following fields:


typedef struct _drmModeRes {
    int count_fbs;
    uint32_t *fbs;
    int count_crtcs;
    uint32_t *crtcs;
    int count_connectors;
    uint32_t *connectors;
    int count_encoders;
    uint32_t *encoders;
    uint32_t min_width, max_width;
    uint32_t min_height, max_height;
} drmModeRes, *drmModeResPtr;

  下图显示各个组件,以及组件之间的关联关系。在DRM的函数名中称作资源(Resource)。如drmModeGetResources()。
在这里插入图片描述
  每种资源的结构都定义了一个成员,唯一标识这个资源。如drmModeCrtc的crtc_id、drmModeConnector的connector_id、drmModeEncoder的encoder_id、drmModePlane的plane_id。

  显示设备的设置、状态,保存在若干结构、变量中,如下图。如drmModeModeInfo,保存设备大小,刷新率。drmModeConnection保存连接状态。
在这里插入图片描述

4.Uos kernel libdrm

uos@uos-PC:/usr/lib/x86_64-linux-gnu$ ls -l libdrm*
lrwxrwxrwx 1 root root     22 924 14:52 libdrm_amdgpu.so.1 -> libdrm_amdgpu.so.1.0.0
-rw-r--r-- 1 root root  43400 924 14:52 libdrm_amdgpu.so.1.0.0
lrwxrwxrwx 1 root root     21 924 14:52 libdrm_intel.so.1 -> libdrm_intel.so.1.0.0
-rw-r--r-- 1 root root 147248 924 14:52 libdrm_intel.so.1.0.0
lrwxrwxrwx 1 root root     23 924 14:52 libdrm_nouveau.so.2 -> libdrm_nouveau.so.2.0.0
-rw-r--r-- 1 root root  39216 924 14:52 libdrm_nouveau.so.2.0.0
lrwxrwxrwx 1 root root     22 924 14:52 libdrm_radeon.so.1 -> libdrm_radeon.so.1.0.1
-rw-r--r-- 1 root root  51392 924 14:52 libdrm_radeon.so.1.0.1
lrwxrwxrwx 1 root root     15 924 14:52 libdrm.so.2 -> libdrm.so.2.4.0
-rw-r--r-- 1 root root  76448 924 14:52 libdrm.so.2.4.0

5.modetest 应用

  它是由 libdrm 提供的测试程序,可以查询显示设备的特性,进行基本的显示测试,以及设置显示的模式。

编译生成目录:libdrm/builddir/tests/modetest

  modetest 查看帮助信息

$ modetest -h
usage: modetest [-acDdefMPpsCvrw]

Query options:

-c      list connectors
-e      list encoders
-f      list framebuffers
-p      list CRTCs and planes (pipes)

Test options:
    ...
Generic options:

-d      drop master after mode set
-M module       use the given driver
-D device       use the given device

Default is to dump all info.

refer to

  • https://waynewolf.github.io/2012/09/05/libdrm-samples/
  • https://www.jianshu.com/p/4a6820b94e3e
  • Linux DRM API - NVIDIA
  • https://docs.mesa3d.org/meson.html
  • https://zhuanlan.zhihu.com/p/341895843
  • https://software.intel.com/content/www/us/en/develop/documentation/intel-joule-getting-started/top/programmers-guide/hdmi-display-and-graphics/graphics-framework.html
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐