menu

Graphics User Guide(Rockchip Linux)

rockchip linux平台的graphic,和以往大家所习惯所不同的是,我们应该是最先全面应用上drmdmabuf的arm linux平台。优势是,通用的架构,在上面客制化会很容易,可以利用很多现有组件,现在有很多基础开源项目的开发,都开始基于rockchip平台来作为arm端的适配平台。但缺点是,确实大家都不是很理解这些东西,实际应用起来需要一个学习过程。

wiki资料点这里

1. hardware

1.1. vop

vop是display单元,用来显示图像 (比如输入nv12,rgb的buffer,显示到屏幕。输入1080p的图像,显示4k大小)。

rk3288有两个vop,vop有3个图层,前两个支持到4k分辨率,后一个鼠标层只有64×64。
rk3399同rk3288。
rk3036只有一个vop,2个图层,一个支持1080p,一个720p。

1.1.1. API

  • libdrm

1.2. gpu

gpu提供opengles api,适合做3d图形和2d图形的加速。

1.2.1. API

  • opengles
  • egl
  • opencl

2. software

先看这个结构图,有什么不理解可以留言。

重点理解libdrm,wayland和x11(compositor),mesa和libmali,qt和gtk(applcation)的关系。这张图理解了,写graphic就很轻松,不理解,就会一头雾水。

2.1. libdrm

libdrm是drm下沟通驱动和用户层的库。过去app可能是直接使用open(fb)这样的方式来和图形驱动沟通,但是在现在的硬件演化下,已经不合适了。比如硬件

  • 有多个图层怎么办?
  • 有多个屏幕怎么办?
  • 怎么处理vsync的问题,怎么同步不撕裂?
  • 怎么利用上dmabuf,做到memory zero-copy?

libdrm的存在就是用来方便用户层和驱动这些问题,提供API给X11, Wayland这样的display backend使用。如果你的程序比较简单,比如一个广告机循环播放视频,那是可以直接调用libdrm,但是不建议直接使用libdrm的api。原因很多:

  • 首先,你肯定不熟悉libdrm,因为libdrm本身是一个比较新的api,而且接触者局限在相关的drm driver developer和wayland/xserver developer这些人身上。
  • libdrm的演进比较快,比如说api还分atomic和legacy,你可能看到的资料和你现在用的完全不一样,只有熟悉演进记录的人才行。
  • 很多效果依赖于厂商的实现,甚至rockchip还有修改很多core API的表现效果来辅助我们内部产品项目,所以同个API在不同平台表现有可能完全不同的

当然,这里不是让你用x11和wayland,而是用我们封装好的东西。 比如,广告机循环播放视频,那最好是用gstreamer,然后选kmssink显示,而不是直接调用libdrm的api。

2.1.1. 简单的理解

drm里有crtc,plane,connector这三个东西,可以理解

  • connector就是屏幕,比如一个hdmi一个connector num, 一个dsi一个connector num
  • crtc表示vop, 一个屏幕一般对应一个crtc
  • plane就是图层,比如视频层在plane2,UI在plane1, 视频在UI上面

drm里api分两套,legacy和atomic。

legacy看名字就是早期的api,我们现在大部分程序也都是用的legacy api。 里面有几个关键的funciton要注意下,drmModeSetCrtc包括了drmModeSetPlane包括了drmModePageFlip

drmModeSetCrtc一般是用来设置UI层,同时设置分辨率用,这里设下的size最后我改到屏幕的分辨率。在rockchip的bsp kernel上drmModeSetCrtc给出的buffer size不需要等于我们要设置的分辨率,这是为了实现在4k的屏幕上使用1080p的UI而做的,不过要注意,这是rockchip自己瞎改的。

drmModeSetPlane用来设置不同图层的显示,比如视频。参数上分别是要显示buffer fd,要操作的图层,要显示的大小,buffer的大小。他会缩放buffer显示到屏幕上。在rockchip平台上这个api是async的,两续调用两次,前面的就被覆盖了,可能需要drmwaitvblank一下,不过要注意,一般内核不会这样的。

为什么rockchip要改这么多地方呢。因为我们想在legacy的api上也完成多图层的显示。想下,我现在用两个图层,图层1和图层2,我现在图层1调用一次drmModeSetPlane,图层2调用一次drmModeSetPlane,然后他们都等一个vsync单位的时间,那假设屏幕刷新率60hz,我们的最大帧数是不是只有30fps了? 为了解决这个问题,上游的人又开发了atomic的api。

atomic api的实质可以理解为一个提交包括了所有的图层的更新信息。这样就不用调用两次drmModeSetPlane了,而是一次的drmModeAtomicCommit,跟上所有的参数。 atomic还有一个很有用的地方在他可以设置plane的zpos,这样就可以自由交换overlay plane和primary plane的显示层级了。之前我们在legacy api(kmssink)的时候都在kernel里hard code层级,但用atomic(mpv)的时候就不需要这样做,设置zpos后,osd(primary layer)也能在video(overlay layer)上面显示了。

2.1.2. 资料

leagacy的实例

atomic的实例

当然最好还是看libdrm的文档和test程序。 如果你是自己写小程序,可以把mpp+libdrm那demo里的rkdrm下的文件抽出来自己用,还是挺方便的。如果只是写给rockchip平台用,就legacy api,如果还有多个平台的需求,就研究下atomic了。

2.2. libmali

libmali单独拉出来讲一下,这个东西就是arm提供的userspace gpu驱动。

前面说了,gpu是提供opengles,egl,opencl api的,所以你要这几个工作,就需要把libmali加进rootfs里。

默认的binary我们都会传github上: https://github.com/rockchip-linux/libmali

命名规则: gpu型号-软件版本-硬件版本(如果有的话,比如说r1p0区分3288和3288w)-编译选项。

要注意编译选项

  • 不带后缀。是x11-gbm,注意gbm是配置drm使用的memory机制,如果不是3.10的kernel,不要用fbdev的。
  • gbm。 是给qteglfs这样的程序用的,不依赖x11,wayland。
  • wayland。 wayland-gbm, 给wayaland使用

需要替换的系统链接: x11 or none: https://github.com/rockchip-linux/libmali/blob/rockchip/debian/libmali-rk-midgard-t76x-r14p0-r0p0.links wayland: https://github.com/rockchip-linux/libmali/blob/rockchip/debian/libmali-rk-midgard-t76x-r14p0-r0p0-wayland.links

2.2.1. zero-copy

用mali显示dmabuf的数据,比如说摄像头,视频,其实是可以用dmabuf zero-copy机制优化的。 不然载入texture还要cpu去拷贝。

参考:

2.3. x11

就和一般桌面平台差不多,不过要x11要有个gpu性能缺陷的问题。

https://en.wikipedia.org/wiki/X.Org_Server
http://www.comptechdoc.org/os/linux/howlinuxworks/linux_hlxwindows.html
https://dri.freedesktop.org/wiki/DDX/
https://www.freedesktop.org/wiki/Software/Glamor/

2.4. wayland

建议使用yocto sdk做wayland的开发。 不然不回答怎么编译,怎么运行的问题。

效率上wayland要比x11好点,主要是兼容性问题。如果不需要桌面,又要多窗口,可以wayland试试看。

2.4.1. zero-copy

wayland也有zero-copy的配置,可以搜下相关的wayland dmabuf。

2.4.1.1. 资料

https://en.wikipedia.org/wiki/Wayland

2.5. none

不使用x11和wayland就是none啦,这也是我们嵌入式上接触比较多的。 什么minigui啊,sdl啦都是这样的。

不过要支持到drm和opengl这种的,就只有qt了。

2.5.1. qteglfs

QT EGLFS是qt自己实现的一个gui系统,不支持多窗口,但也因此少了window compoiste。
QT EGLFS和dri2的方式也差不多,区别就在于,qt eglfs的font buffer在自己用gpu compoiste后,是直接送给drm去显示,而X里是送Window manager去做compoiste,所以EGLFS在效率上是有优势的。

3. FAQ

3.1. 输出4k,但是UI只想1080p

目前只支持qteglfs实现这种需求。 http://blog.iotwrt.com/tips/2017/06/04/swap-layer/

3.2. 推荐下怎么选display

At present, the recommended choices for fullscreen window are :

  • qt with eglfs plugin
  • EGL program + x11
  • wayland
  • x11

The recommended choices for multi window are :

  • wayland
  • x11

The recommended choices for desktop are :

  • x11

The recommended choices for 4K playback + fullscreen window are :

  • qt with eglfs plugin
  • x11

The recommended choices for 4K playback + multi window are :

  • x11