设为首页收藏本站
查看: 1855|回复: 1

【米尔瑞萨RZ/G2L开发板-创新应用】基于DRM的Linux显示系统

[复制链接]

9

主题

15

回帖

165

积分

注册会员

积分
165
slamdunk 发表于 2023-9-10 22:01:43 | 显示全部楼层 |阅读模式
本帖最后由 slamdunk 于 2023-9-11 10:18 编辑

1、Linux Graphic框架



Linux图形栈简单来说可以分为用户空间程序和kernel空间的驱动两个部分。
其中用户空间包括libdrm库和基于libdrm的APP
kernel空间主要是图显驱动和buffer的管理。
1.png


1.1 DRM简介
Direct Rendering Manager(DRM)是linux内核子系统,负责与显卡交互。 DRM提供一组API,用户空间程序可以使用该API将命令和数据发送到GPU并执行诸如配置显示器的模式设置之类的操作。



DRM位于内核空间中,因此用户空间程序必须使用内核系统调用来请求其服务。DRM检测到的每个GPU都称为DRM设备,并创建了一个设备文件/dev/dri/cardX节点,并使用ioctl调用与DRM进行通信。不同的ioctl对应于DRM API的不同功能。DRM提供了libdrm库,以方便用户空间程序与DRM子系统交互。

基于DRM的Linux显示系统,从APP到底层的大概结构如下图所示。
2.png

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

3.png



本文主要涉及:
1)移植libdrm到rzg2l开发板
2)基于libdrm编写测试APP
3)移植LVGL图形界面

2、移植libdrm


2.1 下载libdrm源码
git clone git://anongit.freedesktop.org/mesa/drm
  1. drm$ tree -L 1
  2. .
  3. ├── amdgpu
  4. ├── android
  5. ├── Android.common.mk
  6. ├── Android.mk
  7. ├── CleanSpec.mk
  8. ├── CONTRIBUTING.rst
  9. ├── core-symbols.txt
  10. ├── data
  11. ├── etnaviv
  12. ├── exynos
  13. ├── freedreno
  14. ├── gen_table_fourcc.py
  15. ├── include
  16. ├── intel
  17. ├── libdrm_lists.h
  18. ├── libdrm_macros.h
  19. ├── libdrm.pc.in
  20. ├── libsync.h
  21. ├── Makefile.sources
  22. ├── man
  23. ├── meson.build
  24. ├── meson_options.txt
  25. ├── nouveau
  26. ├── omap
  27. ├── radeon
  28. ├── README.rst
  29. ├── RELEASING
  30. ├── symbols-check.py
  31. ├── tegra
  32. ├── tests
  33. ├── util_double_list.h
  34. ├── util_math.h
  35. ├── vc4
  36. ├── xf86atomic.h
  37. ├── xf86drm.c
  38. ├── xf86drm.h
  39. ├── xf86drmHash.c
  40. ├── xf86drmHash.h
  41. ├── xf86drmMode.c
  42. ├── xf86drmMode.h
  43. ├── xf86drmRandom.c
  44. ├── xf86drmRandom.h
  45. └── xf86drmSL.c

  46. 15 directories, 28 files
复制代码
2.2 配置libdrm
新建一个cross_file.txt,meson --cross-file指定使用这个cross_file.txt
  1. [binaries]
  2. c = 'aarch64-poky-linux-gcc'
  3. cpp = 'aarch64-poky-linux-g++'
  4. ar = 'aarch64-poky-linux-ar'

  5. [host_machine]
  6. system = 'linux'
  7. cpu_family = 'aarch64'
  8. cpu = 'aarch64'
  9. endian = 'little'
复制代码
   
  1. meson --prefix=$(pwd)/install --cross-file cross_file.txt build
复制代码


2.3 编译libdrm     

  1. cd build

  2. ninja && ninja install
复制代码



编译好的libdrm如下所示:
  1. install$ tree -L 2
  2. .
  3. ├── include
  4. │   ├── freedreno
  5. │   ├── libdrm
  6. │   ├── libkms
  7. │   ├── libsync.h
  8. │   ├── xf86drm.h
  9. │   └── xf86drmMode.h
  10. ├── lib
  11. │   ├── libdrm_amdgpu.so -> libdrm_amdgpu.so.1
  12. │   ├── libdrm_amdgpu.so.1 -> libdrm_amdgpu.so.1.0.0
  13. │   ├── libdrm_amdgpu.so.1.0.0
  14. │   ├── libdrm_freedreno.so -> libdrm_freedreno.so.1
  15. │   ├── libdrm_freedreno.so.1 -> libdrm_freedreno.so.1.0.0
  16. │   ├── libdrm_freedreno.so.1.0.0
  17. │   ├── libdrm_nouveau.so -> libdrm_nouveau.so.2
  18. │   ├── libdrm_nouveau.so.2 -> libdrm_nouveau.so.2.0.0
  19. │   ├── libdrm_nouveau.so.2.0.0
  20. │   ├── libdrm_radeon.so -> libdrm_radeon.so.1
  21. │   ├── libdrm_radeon.so.1 -> libdrm_radeon.so.1.0.1
  22. │   ├── libdrm_radeon.so.1.0.1
  23. │   ├── libdrm.so -> libdrm.so.2
  24. │   ├── libdrm.so.2 -> libdrm.so.2.4.0
  25. │   ├── libdrm.so.2.4.0
  26. │   ├── libkms.so -> libkms.so.1
  27. │   ├── libkms.so.1 -> libkms.so.1.0.0
  28. │   ├── libkms.so.1.0.0
  29. │   └── pkgconfig
  30. └── share
  31.     ├── libdrm
  32.     └── man

  33. 9 directories, 21 files
复制代码

最终要用到的是这个库文件 libdrm.so.2和一些位于build/tests/modetest/目录下的测试工具modetest


2.4 使用modetest测试
将上一步编译好的 libdrm.so.2库放入到板子的/usr/lib, modetest程序copy到板端/usr/bin下。
[h]

执行modetest -M rcar-du查看资源:
可以看出CRTC ID是37,ENCODER ID是38,CONNECTOR ID是39
主图层primary plane ID是32,overlay plane ID是34
  1. modetest -M rcar-du
  2. Encoders:
  3. id      crtc    type    possible crtcs  possible clones
  4. 38      37      none    0x00000001      0x00000001
  5. 44      0       Virtual 0x00000001      0x00000002

  6. Connectors:
  7. id      encoder status          name            size (mm)       modes   encoders
  8. 39      38      connected       HDMI-A-1        0x0             1       38
  9.   modes:
  10.         index name refresh (Hz) hdisp hss hse htot vdisp vss vse vtot)
  11.   #0 1920x1080 60.00 1920 2008 2052 2200 1080 1116 1121 1125 148500 flags: ; type: preferred
复制代码

使用主图层测试:
  1. root@myir-yg2lx:/etc# modetest -M rcar-du -P 32@37:1920x1080
  2. testing 1920x1080@XR24 overlay plane 32
复制代码

11.png
使用overlay图层测试
  1. root@myir-yg2lx:/etc# modetest -M rcar-du -P 34@37:1920x1080
  2. testing 1920x1080@XR24 overlay plane 34
复制代码
12.png

使用Connector测试
  1. root@myir-yg2lx:/etc# modetest -M rcar-du -s 39@37:1920x1080
  2. setting mode 1920x1080-60.00Hz@XR24 on connectors 39, crtc 37
  3. failed to set gamma: Invalid argument
复制代码
13.png


3、编译自己的APP
自己写APP的一般流程如下:


14.png
这里给出Makefile的参考。
在编译之前首先要source /opt/poky/3.1.20/environment-setup-aarch64-poky-linux,
附件中的代码分别是单buffer的,双buffer和基于vsync事件的。详情参考源码。

  1. CC?=$(CC)gcc

  2. CFLAGS_=-I /opt/poky/3.1.20/sysroots/aarch64-poky-linux/usr/include/
  3. CFLAGS_ += -I /opt/poky/3.1.20/sysroots/aarch64-poky-linux/usr/include/libdrm/
  4. LDFLAGS_=-L /opt/poky/3.1.20/sysroots/aarch64-poky-linux/usr/lib/

  5. FLAGS=-ldrm
  6. all:
  7.         $(CC) $(CFLAGS_) $(LDFLAGS_) $(FLAGS)  modeset.c -o modeset
  8.         $(CC) $(CFLAGS_) $(LDFLAGS_) $(FLAGS)  modeset-double-buffered.c -o modeset-double-buffered
  9.         $(CC) $(CFLAGS_) $(LDFLAGS_) $(FLAGS)  modeset-vsync.c -o modeset-vsync

  10. .PHONY: clean
  11. clean:
  12.         rm -f *.o modeset modeset-double-buffered modeset-vsync
复制代码
编译make
编译好的程序copy到板端执行
./modeset /dev/dri/card1


4、基于DRM的LVGL移植

之前有移植基于/dev/fb0的lvgl,现在修改一下lvgl的源码,不使用FB作为后端,改为使用DRM做为后端。


15.png

4.1 Makefile 修改
基于DRM的lvgl,需要用到libdrm和drm的一些头文件,这里指定了libdrm的路径。
  1. # Makefile

  2. cc=$(CC)

  3. LVGL_DIR_NAME ?= lvgl
  4. LVGL_DIR ?= ${shell pwd}

  5. CFLAGS = -O3 -g0 -I$(LVGL_DIR)/

  6. BIN = lvgl-drm

  7. CFLAGS = -I$(LVGL_DIR)/ $(DEFINES) $(WARNINGS) $(OPTIMIZATION) -I$(LVGL_DIR)  -I.

  8. CFLAGS += -I /media/yc/D/DRM-test/DRM-Test/libdrm-2.4.100/install/include
  9. CFLAGS += -I /media/yc/D/DRM-test/DRM-Test/libdrm-2.4.100/install/include/libdrm
  10. LDFLAGS +=-L /media/yc/D/DRM-test/DRM-Test/libdrm-2.4.99/install/lib

  11. LDFLAGS += -lm -ldrm

  12. #Collect the files to compile
  13. MAINSRC = ./main.c

  14. include ./lvgl/lvgl.mk
  15. include ./lv_drivers/lv_drivers.mk
  16. include ./lv_demos/lv_demo.mk

  17. OBJEXT ?= .o

  18. AOBJS = $(ASRCS:.S=$(OBJEXT))
  19. COBJS = $(CSRCS:.c=$(OBJEXT))

  20. MAINOBJ = $(MAINSRC:.c=$(OBJEXT))

  21. SRCS = $(ASRCS) $(CSRCS) $(MAINSRC)
  22. OBJS = $(AOBJS) $(COBJS)

  23. ## MAINOBJ -> OBJFILES

  24. all: default

  25. %.o: %.c
  26.         @$(cc)  $(CFLAGS) -c $< -o $@
  27.         @echo "CC $<"
  28.    
  29. default: $(AOBJS) $(COBJS) $(MAINOBJ)
  30.         $(cc) -o $(BIN) $(MAINOBJ) $(AOBJS) $(COBJS) $(LDFLAGS)
  31.         cp $(BIN) /media/yc/D/rz-gl2/work_tmp

  32. clean:
  33.         rm -f $(BIN) $(AOBJS) $(COBJS) $(MAINOBJ)

复制代码
4.2 lv_drv_conf.h文件修改




这里默认使用的是card0,修改成card1



4.3 main.c文件修改



4.4 编译
make -j8
将编译出来的lvgl-drm文件copy到板端运行即可
16.png
1.png

modeset.zip

21.03 KB, 下载次数: 419

modeset源码

libdrm.so.zip

229.5 KB, 下载次数: 437

lvgl.zip

2.94 MB, 下载次数: 434

modeset-vsync.zip

25.11 KB, 下载次数: 434

double-buffer& vsync.zip

10.34 MB, 下载次数: 455

2.zip

1.02 MB, 下载次数: 435

回复

使用道具 举报

9

主题

15

回帖

165

积分

注册会员

积分
165
 楼主| slamdunk 发表于 2023-9-10 22:12:30 | 显示全部楼层
本帖最后由 slamdunk 于 2023-9-14 22:32 编辑

图片要上传才能显示
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录

本版积分规则

Archiver|手机版|小黑屋|米尔科技论坛   

GMT+8, 2024-11-23 16:09 , Processed in 0.063911 second(s), 23 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表