DRM (Direct Rendering Manager) 的发展历史

前言

了解 DRM 的发展历史,对于学习 DRM 驱动开发的人员来说,具有一定的帮助。
因此本人决定将 Wiki 上 Direct Rendering Manager 文章中的 History 章节翻译成中文,并重新组织语言形式,方便初学者阅读和理解。

正文

1999年,Precision Insight公司首次为 XFree86 4.0 Server 开发 DRI 显示框架,主要用于更好的适配 3dfx 公司的显卡。也就是在那时提交了第一版 DRM 代码,并以 kernel patch 的形式提交到了 Mesa3D 的 drm 仓库中。

当时的 mesa/drm 仓库其实是包含两部分代码的,一部分为 user space 代码(即后来的 libdrm),另一部分为 kernel space 代码(即后来的 drm 驱动)。

点击此处,查看 DRM 的第一版提交。需要注意的是,那个时候的 DRM 代码,主要以 buffer 管理为主,不包含 mode-setting 的部分。

同年晚些时候,该笔 patch 的 kernel 部分被 merge 到 kernel 2.3.18 主线中,当时的 drm 源码被放到了 /drivers/char/drm/ 目录下,作为字符设备来使用。

点击此处,查看该kernel提交。

在接下来的几年里,drm 驱动所支持的显卡数量不断在扩增。到2001年1月,Linux 2.4.0 版本发布时,除了已经支持的 3dfx Voodoo3 显卡外,还支持 Creative Labs GMX 2000Intel i810Matrox G200/G400ATI Rage 128 这些显卡。在后续的 Linux 2.4.x 系列版本中,随着 ATI Radeon 显卡,SiS 显卡, Intel 830M 以及再后来的集成显卡这些驱动的合入,DRM 所支持的显卡列表不断的被扩充。

在2004年的下半年,DRM 被分割成了2部分:DRM CoreDRM Driver ,并被 merge 到 kernel 2.6.11 主线版本中。该分割允许多个 DRM 驱动同时访问多个设备,为 multi-GPU 的支持开辟了道路,此次分割也被称为 DRM core/personality split

多年来,开发者们都一致认为,应该把所有 mode-setting 相关的代码放到 kernel 源码中去。但是显卡厂商却对此颇有争议,他们认为实现 mode-setting 操作的唯一途径,就是调用他们显卡厂商自己提供的 API,而这些 API 往往是被固化在显卡的 BIOS 中的,并且只能在 X86 实模式 下运行。这就导致 Linux kernel 根本无法调用这些显卡 API,因为 kernel 本身运行在 X86 保护模式 下。直到后来 Luc Verhaegen 和其它开发人员找到了一种新的方法,使用 natvie mode-setting 来代替 BIOS,这种局面才被打破。该方法证明了使用 kernel 的代码也可以完成 mode-setting 操作,这就为后来的 Kernel Mode Setting 代码奠定了基础。

2007年5月,Jesse Barnes (来自 Intel) 发布了第一版 drm-modesetting API 提案,并在 Intel GPU i915 的 DRM 驱动中实现了 mode-setting 的操作。同年12月,Jerome Glisse 开始将 native mode-setting 代码添加到 ATI Radeon 显卡的 DRM 驱动中。2008年,该项任务的 API 和 driver 部分的工作仍在持续进行,但因为依赖 DRM 另一个重要组件 —— Memory Manager,而迟迟被延期,因为 mode-setting 需要依赖 Memory Manager 来管理 framebuffer。

2008年10月,Linux kernel 2.6.27 进行了一次重大的源码重组,随后 DRM 也迎来了历史性的重大修改:DRM 的整套源码被放到了 /drivers/gpu/drm/ 目录下,不同的GPU厂商代码也被放到了各自的子目录下,同时头文件也被移到了 /include/drm 目录下。

drm重组修改:drm: reorganise drm tree to be more future proof.

随着显存管理的复杂性日益增加,开发人员也想出了多种方法来解决这类问题。最先出场的是 Translation Table Maps (TTM) 内存管理器,由 Thomas Hellstrom (Tungsten Graphics) 与 Eric Anholt (Intel) 和 Dave Airlie (Red Hat) 联合开发完成。在2007年11月,有人就提议将 TTM 纳入 kernel 2.6.25 主线版本中。在2008年5月,该提案又再一次被提及,可是最终还是被驳回了。取而代之的,是一种新的方案,叫做 Graphics Execution Manager (GEM)。GEM 最初是由 Intel 的 Keith Packard 和 Eric Anholt,为了解决 i915 drm driver 的内存管理问题,而开发的一种更加简单的内存管理方案。GEM 后来受到了广泛好评,并被 merge 到了 Linux kernel 2.6.28 版本中,于2008年12月正式发布。而在此期间,TTM 不得不苦苦等待,直到2009年9月,因为新的 Radeon KMS DRM driver 的要求,最终才被 merge 到 Linux 2.6.31 主线版本中。

有了内存管理来操作 buffer object,DRM 开发人员终于可以将早已完成的 mode-setting API 及相关动代码添加到 kernel 中了,这些 API 被称作 Kernel Mode-setting (KMS),而实现这些 API 的驱动也被称之为 KMS Drivers。2009年3月,KMS 被合入到 Linux kernel 2.6.29 版本中,附带一起的还有 i915 KMS 驱动。从 libdrm 2.4.3 版本开始,KMS API 被导出到了用户空间,而Intel DDX 显卡驱动(位于用户空间的 X.Org 中)则是第一家使用 GEM 和 KMS APIs 的厂商驱动。2009年9月,Radeon KMS DRM 驱动被添加到了 Linux 2.6.31 发行版中,该驱动虽然使用的是 TTM 内存管理器,但是却向上层提供了与 GEM 相兼容的 API 和 ioctl。

从2006年开始,nouveau 项目就开始在 Linux kernel 的非官方版本上开发用于免费使用的 NVIDIA DRM 驱动。在2010年,nouveau 项目的源代码被当作一款实验性的驱动 merge 到了 Linux2.6.33 版本中。在提交的过程中,该驱动也被转换成了 KMS 版本,同时使用 TTM 作为它的内存管理器。

KMS API (包括 GEM 在内) 是 DRM 开发过程中的一个重要里程碑,但是它并没有就此止步不前,而是在接下来的几年里不断的优化自己的 API。在 Linux 2.6.33 版本中,KMS 添加了 page flip 操作,用来与异步 VBLANK 事件进行同步,当时只有 i915 驱动支持该操作。后来在 Linux 2.6.38 发行版中, radeon 和 nouveau 驱动也都添加了对该操作的支持。该 page flip 对应的上层接口也被添加到了 libdrm 2.4.17 版本中。2011年初,在 Linux 2.6.39 发布周期内, dumb buffer 被添加到了 KMS API 中。所谓 “dumb buffer”,就是该 buffer 的操作不依赖于硬件或相关加速器,多用于简单 buffer 的应用场合,适合做 framebuffer 使用。它的目的是降低应用程序操作 DRM 的复杂度,比如 Plymouth 这种应用程序,本身使用场景就比较简单,无需使用 driver 所提供的特定 API 来完成 buffer 的操作。从 libdrm 2.4.25 版本开始,这个新特性就被添加进去了。同年晚些时候,KMS 又添加了一个新类型的 object,即 Plane。有些扫描引擎(即CRTC)本身附带硬件合成能力,这些负责硬件合成功能的模块往往被称为 HW overlay,而 Plane 就是用来抽象 overlay 硬件的。从 Linux 3.3 和 libdrm 2.4.30 版本开始,添加了对 Plane 的支持。在 Linux 3.5 和 libdrm 2.4.36 版本发布期间,另一个新增的重要元素,就是 generic object property —— 一种将常用参数添加到 KMS objects 中的方法。Property 的支持,对于那些需要完成特定行为或功能的 objects(如 CRTCs、planes)来说,是一种极其有效的操作方法。

2010年,Dave Airlie 开发出了可以在 DRM 驱动之间进行卸载 GPU 的原型方案,因为 Airlie 当时想要模仿 NVIDIA Optimus 技术,所以它给自己的这项技术命名为 “PRIME”。2011年底,Airlie 恢复了他在 PRIME 上的工作,不过这次是基于 Linux 3.3 引入的一种新的 buffer 共享机制 —— DMA-BUF。DMA-BUF PRIME 基础框架最终于2012年3月完成,并被合入到 Linux 3.4 和 libdrm 2.4.34 版本中。后来在 Linux 3.5 版本发行期间,越来越多的 DRM 驱动实现了对 PRIME 的支持,其中包括 Intel i915 显卡驱动,AMD radeon 显卡驱动以及 NVIDIA nouveau 显卡驱动。

近年来,DRM API 随着一些新的 feature 加入而不断的被扩展。在2013年,作为 GSoC 项目的一项开发计划,David Herrmann 开发出了 Multi-Render Nodes 的功能。他的这部分代码很快被 merge 到了 Linux 3.12 版本中,并作为实验性的功能被 i915、radeon 和 nouveau 驱动所支持。从 Linux 3.17 版本开始,该功能被默认开启使用。2014年,Matt Roper (Intel) 开发并提出了 Universal Plane(或者叫 Unified Plane)的概念,它将 framebuffer (primary plane)、overlay (secondary plane) 和 cursor (cursor plane) 这些 plane 都视为具有相同 API 的 objects,只是这些 objects 的 type 不一样而已。Universal Plane 的实现,具有更少、更通用的 ioctls,使得 DRM API 更加统一(译者注:这里的 universal plane,个人认为翻译成 “万能 plane ” 更贴切,因为它既可以是 primary,也可以是 overlay 或 cursor)。为了兼容旧的 API,DRM Core 将 universal plane 作为驱动的一个附加功能提供给上层使用。在 Linux3.15 和 libdrm 2.4.55 版本中,universal plane 首次亮相,部分驱动(如 Intel i915)也实现了对该功能的支持。

近期 DRM API 最大的优化就是 atomic mode-setting API,它将原子操作的概念引入到了 mode-setting 和 page flip 操作中。Atomic API 的想法最早是在2012年提出的,Ville Syrjälä (Intel)接管了该 API 设计与实现的主要任务。在他的工作基础上,Rob Clark (TI)采用了同样的方式来实现 atomic page flip 操作。后来在2013年,mode-setting 和 page flip 这两个功能都被整合到同一个 ioctl 中,但是因为需要等待 universal plane 的功能完成,该 feature 一直等到2014年中旬才被合入主线版本。在2014年的下半年,为了让现有的 KMS 驱动转向新的 atomic 框架,Daniel Vetter (Intel)和其它 DRM 开发人员对 atomic 代码做了大量的优化。最终,这些修改都被合入到 Linux 3.19 和 Linux 4.0 发行版中,并且从 Linux 4.2 版本开始默认使用该功能。libdrm 从 2.4.62 版本开始支持这些新的 atomic API,许多驱动也都转而使用这些新的 API。到2018年,又有10个基于 atomic 框架的 DRM 新增驱动被添加到了 Linux kernel 中。

总结

最后用一张图来总结一下 DRM 在历史上的重要事件:

drm-history.png-202.8kB

文章汇总: DRM (Direct Rendering Manager) 学习简介

发布了68 篇原创文章 · 获赞 112 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/hexiaolong2009/article/details/88075520