DRM中的思路

linux已经有过fbdev管理图形适配器的FB,但是不能处理现代基于3D加速GPU的图形硬件。3D加速设备一般需要设置、管理一个在其硬件内部内存的指令序列,然后分发指令。

DRM暴露有设备节点在/dev/dri/cardX,libdrm封装了对这个设备节点的操作。

DRM包含两部分,generic DRM core,以及DRM Driver,DRM Driver是硬件相关部分。DRM core提供基础框架,可以由不同的DRM Driver注册,同时也提供给用户态一个最小的ioctl调用组,硬件无关。DRM Driver负责硬件相关的ioctl调用。

如何提供接口:

DRM core主要提供通过ibdrm包装的系统调用,而DRM Driver部分的ioctl调用一般封装在libdrm-driver里面。一般来说,硬件相关的接口像是内存映射、context管理、DMA操作、AGP管理、vblink控制、fence管理、内存管理和输出管理应该在libdrm-driver。

权限的管理:

DRM事关显示,需要安全,因此DRM有提供ioctl SET_MASTER,执行过此syscall的程序就可以成为唯一的DRM-Master显示管理程序,执行ioctl DROP_MASTER也可以放弃DRM-Master身份,一般X server就是DRM-Master。其他的非DRM-Master用户态程序通过DRM-Auth,具体过程是:执行ioctl GET_MAGIC得到一个32bit魔数,然后传给DRM-Master -> DRM-Master用此32位魔术ioctl AUTH_MAGIC给DRM设备 -> DRM设备给发起Auth的非DRM-Master应用持有的与此魔数对应的fd授权。

DRM中的GEM(Graphics Execution Manager)

从DRI2/3的表述,每个渲染实体都开始持有自己的back buffer,并且从显卡申请的内存也可以context切换出去后一直持有,这些被持有的内存就需要DRM在内核中管理起来,GEM就提供这些API,包括申请、释放这些个GPU用的内存(可能集显在内存,独显在显卡),姑且称显存。

显存在进程间传递:

申请了现存就可以得到一个32bit数,把这个数字告知另一个用户态程序即可实现现存的传递、共享,这其实是有安全问题的,任何应用都可以随便猜个数,然后读、写内容。不过这个问题后来通过引入DMA-BUF解决,DMA-BUF是用于在多设备间共享 DMA缓存的,比如说Video4Linux设备和显示器就可以通过DMA-BUF实现0复制的数据传输,任意linux设备驱动都可以实现此API的生产和/或消费者,DMA-BUF一开始适用于集显+独显的共享FB,然后用的愈加的多;提供有ioctl将GEM句柄与DMA-BUF fd相互转换,转成DMA-BUF的GEM对象就可以通过IPC socket的SCM_RIGHTS完成传递。DRI3在client和Xserver间传buffer、Wayland都是这样用的。

GPU-CPU间的内存同步:

现代计算机到处都是cache,cache对齐和保障CPU-GPU内存一致就需要考虑,也就有了对硬件实现的高度依赖,对于集显,没有独立的内存,比较好说,基于UMA(Uniform Memory Architecture)划分内存域进行管理;而独显则大多选择将GEM的API实现在用户态。

TTM(Translation Table Maps)

TTM出于GEM之前,设计用于管理GPU可能访问的不同类型的内存的管理,独立显存(Video RAM即VRAM)、通过IOMMU访问的系统RAM(即GART-Graphics Address Remapping Table)、以及CPU不能直接访问的显存;还有一个功能就是维护内存一致性。用户态图形程序要访问显存时,如向显存中装数据,TTM需要做映射使CPU可访问,或通过GART让GPU访问系统内存,这些都需要处理内存一致性问题。

另一个重要的TTM概念是fences,内存屏障;这是一个管理CPU-GPU内存一致性的基础机制,一块共享内存,GPU使用完,其他想要使用这块内存用户态程序就可以得到提醒,其实就像是互斥锁。

TTM想把独显、集显用一致的方法统一管起来,但这导致TTM太复杂,API太多;GEM更简单的、API比TTM更好的;不过TTM很适合独显、有IOMMU的场合,所以就把TTM包在了GEM的API下面。AMD和NVIDIA显卡都这么干的。

Render Nodes

一开始DRM设备/dev/dri/cardX是特权操作(modsetting/其他显示控制)和非特权操作(如渲染操作)公共使用的设备节点,致使仅部分可靠的用户态程序(如X,作为DRM-Master)才有全部的DRM API的访问权限,其他的用户态程序想要使用GPU做渲染就只能先去DRM-Auth,然后才能执没有特权操作的DRM API。这一设计需要如X server这样的程序必须运行,而很多使用GPU渲染的程序并不是为了显示(比如我现在这样的),不显示就不需要这么关注安全,毕竟只是用用硬件,得个结果,而这个结果不是为了迷惑显示器前的人;再这样的考量下,Render Node的概念:把DRM用户态API分成特权和非特权的,分开使用GPU,也就是添加了设备/dev/dri/renderDX。这样想要利用GPU算力而不是为了显示的兄弟们就只要有此设备节点的访问权限就能做计算了,而compositors,X server,以及其他需要modeset API或是特权操作的,还是必须使用/dev/dri/cardX设备节点,像之前一样干活。而Render Node也就不允许通过GEM flink一下就共享buffer的操作,需要转成DMA-BUF fd来共享、传递。

你可能感兴趣的:(linux显示相关,DRM)