用户空间接口

DRM 核心向应用程序导出多个接口,通常旨在通过相应的 libdrm 包装函数使用。此外,驱动程序通过 ioctl 和 sysfs 文件导出设备特定的接口,供用户空间驱动程序和设备感知应用程序使用。

外部接口包括:内存映射、上下文管理、DMA 操作、AGP 管理、垂直同步控制、栅栏管理、内存管理和输出管理。

在此处涵盖通用 ioctl 和 sysfs 布局。我们只需要高级信息,因为手册页应涵盖其余部分。

libdrm 设备查找

当心恶龙!小心陷阱!

为了警告其他试图弄清楚这里发生了什么的人,我将尝试总结一下这个故事。首先,让我们澄清一下名称,因为内核内部、libdrm 和 ioctl 的命名都不同

  • GET_UNIQUE ioctl,由 drm_getunique 实现,通过 libdrm 中的 drmGetBusid 函数进行包装。

  • libdrm drmSetBusid 函数由 SET_UNIQUE ioctl 支持。所有这些代码都在内核中使用 drm_invalid_op() 进行处理。

  • 内部 set_busid 内核函数和驱动程序回调专门由 SET_VERSION ioctl 使用,因为只有 drm 1.0(已被废弃)允许用户空间通过上述 ioctl 设置总线 ID。

  • 涉及的其他 ioctl 和函数的命名是一致的。

对于想知道 drm 1.1 和 1.4 之间有什么区别的人:正确处理 ppc 上总线 ID 中的 pci 域。在 2010 年 libdrm 中才正确实现了这一点,因此无法废弃。没有人知道 drm 1.2 和 1.3 有什么特别之处。

现在是 drm 中设备查找的实际恐怖故事。大致来说,有两种不同的方法,一种是通过总线 ID,另一种是通过设备驱动程序名称。

通过总线 ID 打开相当简单

  1. 首先调用 SET_VERSION 以确保正确处理 pci 域。作为副作用,这会在主结构中填充唯一的名称。

  2. 调用 GET_UNIQUE 从主结构中读取唯一名称,由于步骤 1,该名称与总线 ID 匹配。如果不匹配,则继续尝试下一个设备节点。

按名称打开略有不同

  1. 直接调用 VERSION 以获取版本,并与该 ioctl 返回的驱动程序名称进行匹配。请注意,不会调用 SET_VERSION,这意味着刚刚打开的主节点的唯一名称_未_被填充。尽管使用当前 drm 设备节点始终绑定到一个设备,并且不能像 drm 1.0 那样进行运行时分配。

  2. 匹配驱动程序名称。如果它不匹配,则继续到下一个设备节点。

  3. 调用 GET_UNIQUE,并检查唯一名称的长度是否为零(通过检查字符串中的第一个字节是否为 0)。如果不是这种情况,libdrm 将跳过并继续到下一个设备节点。可能这只是从 drm 1.0 时期复制粘贴过来的,当时设置唯一名称意味着驱动程序已经在使用了,但这只是推测。

长话短说:为了保持按名称打开逻辑的正常运行,当尚未调用 SET_VERSION 时,GET_UNIQUE 必须_不_返回唯一字符串,否则 libdrm 会中断。即使该唯一字符串永远不会改变,并且对于实际打开设备完全无关紧要,因为运行时可分配的设备实例仅在 drm 1.0 中支持,而 drm 1.0 早已过时。但是 drmOpenByName 中的 libdrm 代码仍然存在,因此不能破坏它。

主节点、DRM 主控和身份验证

struct drm_master 用于跟踪打开主设备节点的客户端组。对于每个 struct drm_file,它至少成功一次成为设备主控(通过 SET_MASTER IOCTL 或在没有其他人是当前主控时通过隐式打开主设备节点),都存在一个 drm_master。这在 drm_file.is_master 中注明。所有其他客户端都只有一个指向与其关联的 drm_master 的指针。

此外,只有一个 drm_master 可以是 drm_device 的当前主控。可以通过 DROP_MASTER 和 SET_MASTER IOCTL 或通过隐式关闭/打开主设备节点来切换它。另请参见 drm_is_current_master()

客户端可以使用 GETMAGIC 和 AUTHMAGIC IOCTL 对当前主控进行身份验证(如果它与他们自己的匹配)。与交换主控一起,这允许对整组相互信任的客户端进行控制的设备访问。

bool drm_is_current_master(struct drm_file *fpriv)

检查 priv 是否为当前主控

参数

struct drm_file *fpriv

DRM 文件私有数据

描述

检查 fpriv 是否为其设备上的当前主控。这决定了是否允许客户端运行 DRM_MASTER IOCTL。

大多数需要 DRM_MASTER 的现代 IOCTL 用于内核模式设置 - 假定当前主控拥有不可共享的显示硬件。

struct drm_master *drm_master_get(struct drm_master *master)

引用主控指针

参数

struct drm_master *master

struct drm_master

描述

递增 master 的引用计数,并返回指向 master 的指针。

struct drm_master *drm_file_get_master(struct drm_file *file_priv)

引用 file_privdrm_file.master

参数

struct drm_file *file_priv

DRM 文件私有数据

描述

递增 file_privdrm_file.master 的引用计数,并返回 drm_file.master。如果 file_priv 没有 drm_file.master,则返回 NULL。

从此函数返回的主控指针应使用 drm_master_put() 取消引用。

void drm_master_put(struct drm_master **master)

取消引用并清除主控指针

参数

struct drm_master **master

指向 struct drm_master 指针的指针

描述

这将递减 master 后面的 drm_master,并将其设置为 NULL。

struct drm_master

drm 主控结构

定义:

struct drm_master {
    struct kref refcount;
    struct drm_device *dev;
    char *unique;
    int unique_len;
    struct idr magic_map;
    void *driver_priv;
    struct drm_master *lessor;
    int lessee_id;
    struct list_head lessee_list;
    struct list_head lessees;
    struct idr leases;
    struct idr lessee_idr;
};

成员

refcount

此主控对象的引用计数。

dev

链接回 DRM 设备

unique

唯一标识符:例如 busid。受 drm_device.master_mutex 保护。

unique_len

unique 字段的长度。受 drm_device.master_mutex 保护。

magic_map

已使用的身份验证令牌的映射。受 drm_device.master_mutex 保护。

driver_priv

指向驱动程序私有信息的指针。

lessor

租赁授予者,仅当此 struct drm_master 表示承租人持有来自 lessor 的对象租赁时设置。设备的完整所有者将其设置为 NULL。

一旦在 drm_lease_create() 中设置,出租人不会改变,并且每个承租人都持有一个指向其出租人的引用,该引用会在 drm_lease_destroy() 中销毁时释放。

另请参阅 关于显示资源租赁的部分

lessee_id

承租人的 ID。所有者(即 lessor 为 NULL)始终具有 ID 0。受 drm_device.mode_configdrm_mode_config.idr_mutex 保护。

lessee_list

lessor 的承租人的列表条目,它们被链接到 lessees。不适用于所有者。受 drm_device.mode_configdrm_mode_config.idr_mutex 保护。

lessees

从此租赁的 drm_master 列表。受 drm_device.mode_configdrm_mode_config.idr_mutex 保护。

如果未授予任何租赁,或所有承租人都已被销毁,则此列表为空。由于出租人被其所有承租人引用,因此除非列表为空,否则无法销毁此 master。

leases

租赁给此 drm_master 的对象。受 drm_device.mode_configdrm_mode_config.idr_mutex 保护。

对象在 drm_lease_create() 中一起租赁,并在撤销租赁时一起删除。

lessee_idr

此所有者下的所有承租人(仅在 lessor 为 NULL 时使用)。受 drm_device.mode_configdrm_mode_config.idr_mutex 保护。

描述

请注意,master 结构仅与传统/主设备节点相关,因此每个设备只能有一个,而不是每个 drm_minor 一个。

DRM 显示资源租赁

DRM 租赁提供有关 DRM master 是否可以控制 DRM 模式设置对象的信息。这使得可以创建多个 DRM master 来管理显示资源的子集。

设备的原始 DRM master“拥有”可用的 drm 资源。它可以创建额外的 DRM master,并将其控制的资源“租赁”给新的 DRM master。这使新的 DRM master 可以控制租赁的资源,直到所有者撤销租赁或新的 DRM master 关闭。一些有用的术语

  • “所有者”是一个 struct drm_master,它没有从另一个 struct drm_master 租赁对象,因此“拥有”这些对象。所有者可以标识为 struct drm_master,其 drm_master.lessor 为 NULL。

  • “出租人”是一个 struct drm_master,它将对象租赁给一个或多个其他 struct drm_master。目前,不允许承租人创建子租赁,因此出租人与所有者相同。

  • “承租人”是一个 struct drm_master,它从其他 struct drm_master 租赁对象。每个承租人仅从 drm_master.lessor 中记录的单个出租人租赁资源,并在 drm_master.leases 中持有其租赁的对象集。

  • “租赁”是出租人和承租人之间的合同,用于标识承租人可以控制哪些资源。租赁的所有资源必须由出租人拥有或租赁给出租人,并且不允许出租人将同一对象租赁给多个承租人。

任何 struct drm_master “控制”的对象集仅限于其租赁的对象集(对于承租人)或所有对象(对于所有者)。

无法通过各种状态操作 ioctl 修改不由 struct drm_master 控制的对象,并且返回给用户空间的任何状态都将被编辑,使其看起来处于空闲和/或不可用状态。例如,连接器始终报告“已断开连接”,而编码器报告没有可能的 crtc 或克隆。

由于每个承租人都可以从单个出租人租赁对象,因此显示资源租赁形成一个 struct drm_master 的树。由于目前不允许承租人创建子租赁,因此树深度限制为 1。当顶层设备所有者通过 SETMASTER 或 DROPMASTER IOCTL 更改时,所有这些都将同时激活,因此 drm_device.master 指向租赁树顶部的所有者(即 struct drm_master,其 drm_master.lessor 为 NULL)。可以通过所有者的 drm_master.lessee_idr 搜索从所有者租赁对象的所有承租人的完整列表。

开源用户空间要求

与大多数其他内核子系统相比,DRM 子系统对新的 uAPI 的用户空间方面需要什么有更严格的要求。此部分解释了这些要求的具体内容以及它们存在的原因。

简而言之,任何添加 DRM uAPI 的操作都需要相应的开源用户空间补丁,并且这些补丁必须经过审查,并准备好合并到合适且规范的上游项目中。

GFX 设备(显示和渲染/GPU 方面)是非常复杂的硬件,用户空间和内核必须非常紧密地协同工作。渲染和模式设置的接口必须非常广泛和灵活,因此几乎不可能为每种可能的极端情况精确定义它们。反过来,这使得实际上不可能区分用户空间要求的行为与为了避免回归而不能更改的行为,以及只是当前实现的偶然产物。

如果无法访问所有用户空间用户的完整源代码,则意味着无法更改实现细节,因为用户空间可能会在细微细节上依赖当前实现的偶然行为。并且在无法访问源代码的情况下调试此类回归几乎是不可能的。因此,这意味着

  • Linux 内核的“无回归”策略实际上仅适用于 DRM 子系统的开源用户空间。如果用户空间中的闭源 blob 驱动程序使用与开放驱动程序相同的 uAPI,DRM 开发人员会很乐意,但它们必须以与开放驱动程序完全相同的方式执行此操作。创造性地(滥用)接口会导致(过去通常会)出现故障。

  • 任何新的用户空间接口都必须具有开源实现作为演示工具。

需要开源用户空间的另一个原因是 uAPI 审查。由于 GFX 堆栈的内核和用户空间部分必须如此紧密地协同工作,因此代码审查只能通过查看双方来评估新接口是否实现了其目标。确保接口确实完全覆盖了用例会导致一些额外的要求

  • 开源用户空间不能是玩具/测试应用程序,而应该是真实的东西。具体来说,它需要处理所有常见的错误和极端情况。这些通常是新 uAPI 崩溃的地方,因此对于评估建议接口的适用性至关重要。

  • 用户空间部分必须根据该用户空间项目的标准进行全面审查和测试。例如,对于 mesa 来说,这意味着 piglit 测试用例以及在邮件列表上的审查。这同样是为了确保新的接口确实能完成工作。用户空间方面的审查者还应该在内核 uAPI 补丁上提供 Acked-by,表明他们认为提议的 uAPI 是合理的,并且针对用户空间的使用进行了充分的文档化和验证。

  • 用户空间补丁必须针对规范的上游版本,而不是某些供应商的分支。这是为了确保没有人通过快速分支来逃避审查和测试要求。

  • 内核补丁只有在满足以上所有要求后才能合并,但它必须在用户空间补丁落地之前合并到 drm-next 或 drm-misc-next 中。uAPI 总是从内核流出,反过来做会使 uAPI 定义和头文件存在分歧的风险。

这些要求相当严格,但都是从多年来匆忙添加 uAPI 并几乎立即后悔的痛苦经历中总结出来的。GFX 设备变化非常快,至少每隔几年就需要范式转变和一整套新的 uAPI 接口。再加上 Linux 内核保证现有用户空间运行 10 年以上,这对 DRM 子系统来说已经相当痛苦了,同一个事物存在多个不同的 uAPI。如果我们每年再添加一些完全错误的 uAPI,那将是完全无法管理的。

渲染节点

DRM 核心为用户空间提供了多个字符设备供使用。根据打开的设备不同,用户空间可以执行不同的操作集(主要是 ioctl)。主节点始终被创建并称为 card<num>。此外,还创建了一个当前未使用的控制节点,称为 controlD<num>。主节点提供所有遗留操作,并且历史上是用户空间使用的唯一接口。随着 KMS 的引入,控制节点被引入。但是,计划中的 KMS 控制接口从未编写,因此控制节点至今仍未使用。

随着离屏渲染器和 GPGPU 应用程序的使用增加,客户端不再需要运行合成器或图形服务器来使用 GPU。但是,DRM API 要求非特权客户端在获得 GPU 访问权限之前向 DRM-Master 进行身份验证。为了避免此步骤并允许客户端无需身份验证即可访问 GPU,引入了渲染节点。渲染节点仅服务于渲染客户端,也就是说,不能在渲染节点上发出模式设置或特权 ioctl。只允许非全局渲染命令。如果驱动程序支持渲染节点,则必须通过 DRIVER_RENDER DRM 驱动程序功能来声明它。如果不支持,则必须将主节点与传统的 drmAuth 身份验证过程一起用于渲染客户端。

如果驱动程序声明支持渲染节点,则 DRM 核心将创建一个单独的渲染节点,称为 renderD<num>。每个设备将有一个渲染节点。除了 PRIME 相关的 ioctl 之外,此节点上将不允许任何其他 ioctl。特别是 GEM_OPEN 将被明确禁止。有关可在渲染节点上使用的与驱动程序无关的 ioctl 的完整列表,请参阅 drm_ioctl.c 中标记为 DRM_RENDER_ALLOW 的 ioctl。渲染节点旨在避免在客户端猜测传统接口上的 flink 名称或 mmap 偏移量时发生的缓冲区泄漏。除了此基本接口之外,驱动程序还必须将其与驱动程序相关的仅渲染 ioctl 标记为 DRM_RENDER_ALLOW,以便渲染客户端可以使用它们。驱动程序作者必须小心,不要在渲染节点上允许任何特权 ioctl。

通过渲染节点,用户空间现在可以通过基本文件系统访问模式来控制对渲染节点的访问。不再需要运行在特权主/传统节点上对客户端进行身份验证的图形服务器。相反,客户端可以打开渲染节点并立即获得 GPU 访问权限。客户端(或服务器)之间的通信通过 PRIME 完成。不支持从渲染节点到传统节点的 FLINK。新客户端不得使用不安全的 FLINK 接口。

除了删除所有模式设置/全局 ioctl 之外,渲染节点还删除了 DRM-Master 的概念。没有理由将渲染客户端与 DRM-Master 关联,因为它们独立于任何图形服务器。此外,它们无论如何都必须在没有任何正在运行的主服务器的情况下工作。如果驱动程序支持渲染节点,则必须能够在没有主对象的情况下运行。另一方面,如果驱动程序需要在客户端之间共享用户空间可见且可跨越打开文件边界访问的状态,则它们不能支持渲染节点。

设备热插拔

注意

以下是计划。实现尚未完成(2020 年 5 月)。

图形设备(显示和/或渲染)可以通过 USB(例如显示适配器或扩展坞)或 Thunderbolt(例如 eGPU)连接。最终用户可以在使用此类设备时热插拔它们,并期望至少机器不会崩溃。热插拔 DRM 设备造成的任何损坏都需要尽可能地加以限制,并且必须给用户空间机会来处理它(如果需要)。理想情况下,拔下 DRM 设备仍然可以让桌面继续运行,但这需要在整个图形堆栈中得到明确的支持:从内核和用户空间驱动程序,到显示服务器,通过窗口系统协议,以及在应用程序和库中。

其他应该导致相同情况的场景是:GPU 崩溃无法恢复、PCI 设备从总线上消失或强制解除物理设备与驱动程序的绑定。

换句话说,从用户空间的角度来看,一切都需要或多或少地保持正常运行,直到用户空间停止使用消失的 DRM 设备并完全关闭它为止。用户空间将从设备删除的 uevent、ioctl 返回 ENODEV(或驱动程序特定的 ioctl 返回驱动程序特定的内容)或 open() 返回 ENXIO 中得知设备消失。

只有在用户空间关闭所有相关的 DRM 设备和 dmabuf 文件描述符并删除所有 mmap 之后,DRM 驱动程序才能拆除不再存在的设备的实例。如果同一物理设备在此期间以某种方式重新出现,则它将是一个新的 DRM 设备。

与 PID 类似,chardev 次设备号不会立即回收。与之前分配的相比,新的 DRM 设备始终选择下一个空闲的次设备号,并在次设备号耗尽时回绕。

该目标至少对内核和驱动程序提出了以下要求。

KMS UAPI 的要求

  • KMS 连接器必须将其状态更改为断开连接。

  • 传统的模式设置和页面翻转以及原子提交(无论是真实的还是 TEST_ONLY)以及任何其他 ioctl 要么失败并返回 ENODEV,要么伪造成功。

  • 挂起的非阻塞 KMS 操作会传递用户空间期望的 DRM 事件。这也适用于伪造成功的 ioctl。

  • 打开底层设备已消失的设备节点将失败并返回 ENXIO。

  • 尝试在消失的 DRM 设备上创建 DRM 租约将失败并返回 ENODEV。现有的 DRM 租约保持不变并按上述方式工作。

渲染和跨设备 UAPI 的要求

  • 所有无法再运行的 GPU 作业都必须强制发出 fence 信号,以避免在用户空间中造成挂起。关联的错误代码是 ENODEV。

  • 某些用户空间 API 已经定义了当设备消失时应该发生的事情(OpenGL,GL ES:GL_KHR_robustnessVulkan:VK_ERROR_DEVICE_LOST 等)。DRM 驱动程序可以自由地以他们认为最好的方式来实现此行为,例如在驱动程序特定的 ioctl 中返回失败并在用户空间驱动程序中处理这些失败,或者依赖于 uevent 等。

  • 指向已消失的内存的 dmabuf 要么会因 ENODEV 而导入失败,要么如果它在消失之前会成功导入,则继续成功导入。另请参阅下面有关已导入 dmabufs 的内存映射。

  • 尝试将 dmabuf 导入到消失的设备将因 ENODEV 而失败,或者如果它在没有消失的情况下会成功,则成功。

  • 打开底层设备已消失的设备节点将失败并返回 ENXIO。

内存映射的要求

内存映射还有其他要求,适用于现有映射和设备消失后创建的映射。如果底层内存消失,则会创建或修改映射,以便读取和写入仍将成功完成,但结果未定义。这适用于用户空间 mmap() 的内存和由 dmabuf 指向的可能映射到其他设备的内存(跨设备 dmabuf 导入)。

引发 SIGBUS 不是一个选择,因为用户空间无法实际处理它。信号处理程序是全局的,这使得它们很难从 Mesa 生成的库等库中正确使用。信号处理程序不可组合,您不能为来自不同供应商的 GPU1 和 GPU2 使用不同的处理程序,以及为 mmaped 常规文件使用第三个处理程序。线程也会给信号处理带来额外的痛苦。

设备重置

GPU 堆栈非常复杂,并且容易出错,从硬件错误、错误的应用程序到许多层之间的所有内容。某些错误需要重置设备才能使其再次可用。本节介绍了当设备重置时 DRM 和用户模式驱动程序的期望,以及如何传播重置状态。

在不污染内核的情况下无法禁用设备重置,这可能会通过收缩器/mmu_notifiers 导致整个内核挂起。用户空间在设备重置中的作用是将消息传播到应用程序,并应用任何阻止有罪应用程序的特殊策略(如果有)。推论是,调试挂起的 GPU 上下文需要硬件支持,以便能够在停止时抢占这样的 GPU 上下文。

内核模式驱动程序

KMD 负责检查设备是否需要重置,并在需要时执行重置。通常,当作业在执行时卡住时会检测到挂起。

将错误传播到用户空间已被证明是很棘手的,因为它与通常的命令流方向相反。因此,为了实现与供应商无关的错误处理,将错误处理添加到了 &dma_fence 对象中,这样驱动程序可以在信号通知它们之前将错误代码添加到它们的 fence 中。有关如何执行此操作以及要使用的错误代码示例,请参阅函数 dma_fence_set_error()

当硬件提交在重置后重新启动时,DRM 调度程序还允许在所有挂起的 fence 上设置错误代码。错误代码也会从硬件 fence 转发到调度程序 fence,以便将错误传递到堆栈的更高层,并最终传递到用户空间。

用户空间可以通过通用的 SYNC_IOC_FILE_INFO IOCTL 以及驱动程序特定的接口查询 Fence 错误。

除了设置 fence 错误之外,驱动程序还应跟踪每个上下文的重置次数,DRM 调度程序提供了 drm_sched_entity_error() 函数作为此用例的助手。重置后,KMD 应拒绝受影响上下文的新命令提交。

用户模式驱动程序

命令提交后,UMD 应检查提交是否被接受或拒绝。重置后,KMD 应拒绝提交,并且 UMD 可以向 KMD 发出 ioctl 以检查重置状态,如果 UMD 需要,可以更频繁地检查。检测到重置后,UMD 将使用相应的 API 错误代码将其报告给应用程序,如下面关于健壮性的部分所述。

健壮性

在重置后尝试保持图形 API 上下文工作的唯一方法是,它是否符合其正在使用的图形 API 的健壮性方面。

图形 API 为应用程序提供了处理设备重置的方法。但是,不能保证应用程序会正确使用这些功能,并且不支持健壮接口的用户空间(例如,非健壮的 OpenGL 上下文或没有任何健壮性支持的 API,如 libva)会将健壮性处理完全留给用户空间驱动程序。关于在这种情况下用户空间驱动程序应该做什么,社区没有强烈的共识,因为所有合理的方法都有一些明显的缺点。

OpenGL

使用 OpenGL 的应用程序应使用可用的健壮接口,如扩展 GL_ARB_robustness (或 OpenGL ES 的 GL_EXT_robustness)。此接口会告知是否发生了重置,如果发生了重置,则所有上下文状态都被视为丢失,并且应用程序会创建新的上下文。对于如果不使用健壮性该怎么办,没有共识。

Vulkan

使用 Vulkan 的应用程序应检查提交的 VK_ERROR_DEVICE_LOST。此错误代码表示,除其他外,发生了设备重置,需要重新创建上下文才能继续。

报告重置原因

除了通过堆栈传播重置以便应用程序可以恢复之外,对于驱动程序开发人员来说,了解导致重置的根本原因确实非常有用。DRM 设备应使用 devcoredump 来存储有关重置的相关信息,以便可以将此信息添加到用户错误报告中。

设备节点上的 IOCTL 支持

首先,只有支持渲染的驱动程序才需要驱动程序私有 IOCTL。内核模式设置已全部标准化,并通过属性扩展。一些现有驱动程序中存在一些例外情况,这些驱动程序定义了供显示 DRM 主节点使用的 IOCTL,但它们都早于属性。

现在,如果您有渲染驱动程序,您始终必须通过驱动程序私有属性来支持它。需要几个步骤来连接所有内容。

首先,您需要在驱动程序的私有 UAPI 头文件 include/uapi/drm/my_driver_drm.h 中定义 IOCTL 的结构。

struct my_driver_operation {
        u32 some_thing;
        u32 another_thing;
};

请确保您遵循 Documentation/process/botching-up-ioctls.rst 中的所有最佳实践。请注意,drm_ioctl() 会自动将结构零扩展,因此请确保您可以在末尾添加更多内容,即不要在那里放置可变大小的数组。

然后,您需要使用 DRM_IO()、DRM_IOR()、DRM_IOW() 或 DRM_IOWR() 之一来定义您的 IOCTL 编号。它必须以 DRM_IOCTL_ 前缀开头

##define DRM_IOCTL_MY_DRIVER_OPERATION \
    DRM_IOW(DRM_COMMAND_BASE, struct my_driver_operation)

DRM 驱动程序私有 IOCTL 必须在 DRM_COMMAND_BASE 到 DRM_COMMAND_END 的范围内。最后,您需要一个 struct drm_ioctl_desc 数组来连接处理程序并设置访问权限

static const struct drm_ioctl_desc my_driver_ioctls[] = {
    DRM_IOCTL_DEF_DRV(MY_DRIVER_OPERATION, my_driver_operation,
            DRM_AUTH|DRM_RENDER_ALLOW),
};

然后将其分配给驱动程序结构中的 drm_driver.ioctls 字段。

有关如何连接驱动程序特定的 IOCTL 的信息,请参阅关于 文件操作 的单独章节。

测试和验证

用户空间 API 的测试要求

新的跨驱动程序用户空间接口扩展(如新的 IOCTL、新的 KMS 属性、sysfs 中的新文件或构成 API 更改的任何其他内容)应在 IGT 中具有该功能的驱动程序无关的测试用例,如果可以使用 IGT 合理地为目标硬件进行此类测试。

使用 IGT 验证更改

有一系列旨在涵盖 DRM 驱动程序的全部功能并可用于检查对 DRM 驱动程序或核心的更改是否会使现有功能退化的测试。此测试套件称为 IGT,其代码和构建和运行说明可在 https://gitlab.freedesktop.org/drm/igt-gpu-tools/ 中找到。

使用 VKMS 测试 DRM API

VKMS 是 KMS 驱动程序的纯软件模型,可用于测试和运行合成器。VKMS 旨在实现虚拟显示,而无需硬件显示功能。这些特性使 VKMS 成为验证 DRM 核心行为以及支持合成器开发人员的完美工具。VKMS 可以在没有显示器的虚拟机中测试 DRM 功能,从而简化一些核心更改的验证。

要使用 VKMS 验证 DRM API 中的更改,请首先设置内核:确保启用 VKMS 模块;编译启用 VKMS 的内核并将其安装在目标计算机中。VKMS 可以在虚拟机(QEMU、virtme 或类似)中运行。建议使用 KVM,至少 1GB RAM 和四个内核。

可以在 VM 中通过两种方式运行 IGT 测试

  1. 在 VM 内部使用 IGT

  2. 从主机使用 IGT 并将结果写入共享目录。

以下是在主机上使用带有共享目录的 VM 运行 igt 测试的示例。此示例使用 virtme

$ virtme-run --rwdir /path/for/shared_dir --kdir=path/for/kernel/directory --mods=auto

在客户机中运行 igt 测试。此示例运行 ‘kms_flip’ 测试

$ /path/for/igt-gpu-tools/scripts/run-tests.sh -p -s -t "kms_flip.*" -v

在此示例中,不构建 igt_runner,而是使用 Piglit(-p 选项)。它创建一个测试结果的 HTML 摘要,并将其保存在文件夹“igt-gpu-tools/results”中。它仅执行与 -t 选项匹配的 igt 测试。

显示 CRC 支持

DRM 设备驱动程序可以向用户空间提供每个帧到达给定硬件组件(CRC 采样“源”)时的 CRC 信息。

用户空间可以通过在 debugfs 中写入文件 dri/0/crtc-N/crc/control 来控制给定 CRTC 中 CRC 的生成,其中 N 是 CRTC 的索引。接受的值是源名称(特定于驱动程序)和“auto”关键字,这将允许驱动程序为此 CRTC 选择帧 CRC 的默认源。

一旦启用帧 CRC 生成,用户空间可以通过读取 dri/0/crtc-N/crc/data 文件来捕获它们。该文件中的每一行在第一个字段中都包含帧号,然后包含许多包含 CRC 数据的无符号整数字段。字段由单个空格分隔,CRC 字段的数量是特定于源的。

请注意,虽然在某些情况下,CRC 是以指定方式计算的,并且计算的是用户空间提供的帧内容(如 eDP 1.3),但通常情况下,CRC 的计算方式是不明确的,并且是对已处理过的帧内容进行计算,处理方式也是不明确的。因此,用户空间无法依赖于为提交的帧内容生成匹配的 CRC 值。在一般情况下,用户空间所能做的最大程度就是比较那些应具有相同内容的帧的报告 CRC 值。

在驱动程序方面,实现工作量很小,驱动程序只需要实现 drm_crtc_funcs.set_crc_sourcedrm_crtc_funcs.verify_crc_source。如果设置了这些 vfunc,则会自动设置 debugfs 文件。需要在驱动程序中调用 drm_crtc_add_crc_entry() 来捕获 CRC 样本。根据驱动程序和硬件的要求,drm_crtc_funcs.set_crc_source 可能会导致提交(甚至是完整的模式设置)。

CRC 结果必须在非完整模式设置的原子提交中保持可靠,因此,如果通过 DRM_IOCTL_MODE_ATOMIC 进行提交会禁用或以其他方式干扰 CRC 生成,则驱动程序必须将该提交标记为完整模式设置(drm_atomic_crtc_needs_modeset() 应该返回 true)。因此,为了确保结果一致,通用用户空间必须在传统的 SETCRTC 或带有 DRM_MODE_ATOMIC_ALLOW_MODESET 的原子提交后重新设置 CRC 生成。

int drm_crtc_add_crc_entry(struct drm_crtc *crtc, bool has_frame, uint32_t frame, uint32_t *crcs)

添加具有帧 CRC 信息的条目

参数

struct drm_crtc *crtc

帧所属的 CRTC

bool has_frame

此条目是否带有帧号

uint32_t frame

这些 CRC 相关的帧号

uint32_t *crcs

CRC 值数组,长度与 #drm_crtc_crc.values_cnt 匹配

描述

对于每个帧,驱动程序轮询 CRC 的来源以获取新数据,并调用此函数将它们添加到用户空间读取的缓冲区中。

Debugfs 支持

DRM_DEBUGFS_GPUVA_INFO

DRM_DEBUGFS_GPUVA_INFO (show, data)

drm_info_list 条目,用于转储 GPU VA 空间

参数

show

drm_info_list 的 show 回调

data

驱动程序的私有数据

描述

驱动程序应使用此宏定义一个 drm_info_list 条目,以提供 debugfs 文件来转储 GPU VA 空间区域和映射。

对于每个 DRM GPU VA 空间,驱动程序应从其 show 回调中调用 drm_debugfs_gpuva_info()

struct drm_info_list

debugfs 信息列表条目

定义:

struct drm_info_list {
    const char *name;
    int (*show)(struct seq_file*, void*);
    u32 driver_features;
    void *data;
};

成员

name

文件名

show

Show 回调。seq_file->private 将设置为与给定 struct drm_minor 上的此信息的实例对应的 struct drm_info_node

driver_features

此条目所需的驱动程序功能

data

驱动程序私有数据,不应特定于设备。

描述

此结构表示一个由 drm 核心创建的 debugfs 文件。

struct drm_info_node

每个 minor 的 debugfs 节点结构

定义:

struct drm_info_node {
    struct drm_minor *minor;
    const struct drm_info_list *info_ent;
};

成员

minor

此节点的 struct drm_minor

info_ent

此节点的模板。

描述

此结构表示一个 debugfs 文件,作为在 struct drm_minor 上的 struct drm_info_list 的实例。

FIXME

我们为渲染和主节点都复制 debugfs 条目是没有意义的,但这是它自然发展的方式。如果需要,应该使用兼容性链接进行修复。

struct drm_debugfs_info

debugfs 信息列表条目

定义:

struct drm_debugfs_info {
    const char *name;
    int (*show)(struct seq_file*, void*);
    u32 driver_features;
    void *data;
};

成员

name

文件名

show

Show 回调。seq_file->private 将设置为与给定 struct drm_device 上的此信息的实例对应的 struct drm_debugfs_entry

driver_features

此条目所需的驱动程序功能。

data

驱动程序私有数据,不应特定于设备。

描述

此结构表示一个由 drm 核心创建的 debugfs 文件。

struct drm_debugfs_entry

每个设备的 debugfs 节点结构

定义:

struct drm_debugfs_entry {
    struct drm_device *dev;
    struct drm_debugfs_info file;
    struct list_head list;
};

成员

dev

此节点的 struct drm_device

file

此节点的模板。

list

所有设备节点的链表。

描述

此结构表示一个 debugfs 文件,作为在 struct drm_device 上的 struct drm_debugfs_info 的实例。

int drm_debugfs_gpuva_info(struct seq_file *m, struct drm_gpuvm *gpuvm)

转储给定的 DRM GPU VA 空间

参数

struct seq_file *m

指向要写入的 seq_file 的指针

struct drm_gpuvm *gpuvm

表示 GPU VA 空间的 drm_gpuvm

描述

转储给定 DRM GPU VA 管理器的 GPU VA 映射。

对于每个 DRM GPU VA 空间,驱动程序应从其 drm_info_list 的 show 回调中调用此函数。

返回值

成功返回 0,如果 gpuvm 未初始化则返回 -ENODEV

void drm_debugfs_create_files(const struct drm_info_list *files, int count, struct dentry *root, struct drm_minor *minor)

为 DRM minor 初始化给定的一组 debugfs 文件

参数

const struct drm_info_list *files

要创建的文件数组

int count

给定的文件数

struct dentry *root

DRI debugfs 目录条目。

struct drm_minor *minor

设备 minor 号

描述

在给定的根目录中创建由 struct drm_info_list 数组表示的给定的一组 debugfs 文件。这些文件将在 drm_debugfs_dev_fini() 时自动删除。

void drm_debugfs_add_file(struct drm_device *dev, const char *name, int (*show)(struct seq_file*, void*), void *data)

将给定文件添加到 DRM 设备 debugfs 文件列表。

参数

struct drm_device *dev

用于 ioctl 的 DRM 设备。

const char *name

debugfs 文件名

int (*show)(struct seq_file*, void*)

显示回调

void *data

驱动程序私有数据,不应是特定于设备的数据。

描述

将给定的文件条目添加到 DRM 设备 debugfs 文件列表中,以便在 drm_debugfs_init 时创建。

void drm_debugfs_add_files(struct drm_device *dev, const struct drm_debugfs_info *files, int count)

将文件数组添加到 DRM 设备 debugfs 文件列表。

参数

struct drm_device *dev

用于 ioctl 的 DRM 设备。

const struct drm_debugfs_info *files

要创建的文件数组

int count

给定的文件数

描述

将一组给定的 debugfs 文件添加到 DRM 设备 debugfs 文件列表中,这些文件由 struct drm_debugfs_info 数组表示。

Sysfs 支持

除了所有标准的东西之外,DRM 为驱动程序提供的 sysfs 交互支持非常少。想要公开其他 sysfs 属性和属性组的驱动程序可以在 drm_device.devdrm_connector.kdev 中附加它们。

在调用 drm_dev_register() 或在热插拔连接器的情况下调用 drm_connector_register() 时,会自动处理注册。注销也由 drm_dev_unregister()drm_connector_unregister() 自动处理。

void drm_sysfs_hotplug_event(struct drm_device *dev)

生成 DRM uevent。

参数

struct drm_device *dev

DRM 设备

描述

dev 指定的 DRM 设备发送 uevent。目前,我们只在 uevent 环境中设置 HOTPLUG=1,但可以扩展以处理其他类型的事件。

任何新的 uapi 都应使用 drm_sysfs_connector_status_event() 来处理连接器状态更改的 uevent。

void drm_sysfs_connector_hotplug_event(struct drm_connector *connector)

为任何连接器更改生成 DRM uevent。

参数

struct drm_connector *connector

已更改的连接器

描述

connector 指定的 DRM 连接器发送 uevent。这将发送一个包含属性 HOTPLUG=1 和 CONNECTOR 的 uevent。

void drm_sysfs_connector_property_event(struct drm_connector *connector, struct drm_property *property)

为连接器属性更改生成 DRM uevent。

参数

struct drm_connector *connector

属性已更改的连接器

struct drm_property *property

已更改的连接器属性。

描述

为指定的 DRM 连接器和属性发送 uevent。目前,我们设置了 HOTPLUG=1 和连接器 ID,以及与更改相关的附加属性 ID。

int drm_class_device_register(struct device *dev)

向 DRM sysfs 类注册新设备。

参数

struct device *dev

要注册的设备。

描述

在 DRM sysfs 类中注册一个新的 struct device。主要由 ttm 使用,以便为其全局设置提供位置。驱动程序永远不应使用此函数。

void drm_class_device_unregister(struct device *dev)

从 DRM sysfs 类注销设备。

参数

struct device *dev

要注销的设备

描述

从 DRM sysfs 类中注销一个 struct device。主要由 ttm 使用,以便为其全局设置提供位置。驱动程序永远不应使用此函数。

VBlank 事件处理

DRM 内核公开了两个与垂直消隐相关的 ioctl。

DRM_IOCTL_WAIT_VBLANK

此 ioctl 接受一个 struct drm_wait_vblank 结构作为其参数,它用于在指定的 vblank 事件发生时阻塞或请求信号。

DRM_IOCTL_MODESET_CTL

此 ioctl 仅用于围绕模式设置更改的用户模式设置驱动程序,以允许内核在模式设置后更新 vblank 中断,因为在许多设备上,垂直消隐计数器会在模式设置过程中的某个时刻重置为 0。现代驱动程序不应再调用此 ioctl,因为使用内核模式设置时,它是一个空操作。

用户空间 API 结构

DRM 公开了许多 UAPI 和结构定义,以便与用户保持一致和标准化的接口。用户空间可以参考这些结构定义和 UAPI 格式与驱动程序通信。

CRTC 索引

CRTC 既有对象 ID,也有索引,它们不是同一回事。在需要为 CRTC 提供密集打包的标识符的情况下(例如 CRTC 的位掩码),会使用索引。struct drm_mode_get_plane 的成员 possible_crtcs 就是一个例子。

DRM_IOCTL_MODE_GETRESOURCES 使用 CRTC ID 数组填充一个结构,CRTC 索引是它在此数组中的位置。

DRM_CAP_DUMB_BUFFER

DRM_CAP_DUMB_BUFFER

描述

如果设置为 1,则驱动程序支持通过 DRM_IOCTL_MODE_CREATE_DUMB ioctl 创建哑缓冲区。

DRM_CAP_VBLANK_HIGH_CRTC

DRM_CAP_VBLANK_HIGH_CRTC

描述

如果设置为 1,则内核支持在 drm_wait_vblank_request.type 的高位中指定一个 CRTC 索引

从内核版本 2.6.39 开始,此功能始终设置为 1。

DRM_CAP_DUMB_PREFERRED_DEPTH

DRM_CAP_DUMB_PREFERRED_DEPTH

描述

哑缓冲区的首选位深度。

位深度是用于指示单个像素颜色的位数,不包括任何填充。这与每个像素的位数不同。例如,XRGB8888 的位深度为 24,但每个像素有 32 位。

请注意,此首选项仅适用于哑缓冲区,与其他类型的缓冲区无关。

DRM_CAP_DUMB_PREFER_SHADOW

DRM_CAP_DUMB_PREFER_SHADOW

描述

如果设置为 1,驱动程序首选用户空间渲染到影子缓冲区,而不是直接渲染到哑缓冲区。为了获得最佳速度,用户空间应该将流式有序内存复制到哑缓冲区,并且永远不要从中读取。

请注意,此首选项仅适用于哑缓冲区,与其他类型的缓冲区无关。

DRM_CAP_PRIME

DRM_CAP_PRIME

描述

支持的 PRIME 共享功能的位字段。请参阅 DRM_PRIME_CAP_IMPORTDRM_PRIME_CAP_EXPORT

从内核版本 6.6 开始,DRM_PRIME_CAP_IMPORTDRM_PRIME_CAP_EXPORT 始终被通告。

PRIME 缓冲区作为 dma-buf 文件描述符公开。请参阅 PRIME 缓冲区共享

DRM_PRIME_CAP_IMPORT

DRM_PRIME_CAP_IMPORT

描述

如果此位在 DRM_CAP_PRIME 中设置,则驱动程序支持通过 DRM_IOCTL_PRIME_FD_TO_HANDLE ioctl 导入 PRIME 缓冲区。

从内核版本 6.6 开始,此位始终在 DRM_CAP_PRIME 中设置。

DRM_PRIME_CAP_EXPORT

DRM_PRIME_CAP_EXPORT

描述

如果此位在 DRM_CAP_PRIME 中设置,则驱动程序支持通过 DRM_IOCTL_PRIME_HANDLE_TO_FD ioctl 导出 PRIME 缓冲区。

从内核版本 6.6 开始,此位始终在 DRM_CAP_PRIME 中设置。

DRM_CAP_TIMESTAMP_MONOTONIC

DRM_CAP_TIMESTAMP_MONOTONIC

描述

如果设置为 0,内核将在 struct drm_event_vblank 中使用 CLOCK_REALTIME 报告时间戳。如果设置为 1,内核将使用 CLOCK_MONOTONIC 报告时间戳。请参阅 clock_gettime(2) 以获取这些时钟的定义。

从内核版本 2.6.39 开始,此功能的默认值为 1。从内核版本 4.15 开始,此功能始终设置为 1。

DRM_CAP_ASYNC_PAGE_FLIP

DRM_CAP_ASYNC_PAGE_FLIP

描述

如果设置为 1,则驱动程序支持用于旧版页面翻转的 DRM_MODE_PAGE_FLIP_ASYNC

DRM_CAP_CURSOR_WIDTH

DRM_CAP_CURSOR_WIDTH

描述

CURSOR_WIDTHCURSOR_HEIGHT 功能返回硬件光标的有效宽度 x 高度组合。其目的是,与硬件无关的用户空间可以查询要使用的光标平面大小。

请注意,跨驱动程序合同仅仅是返回有效的大小;驱动程序可以随意附加其他含义,例如 i915 返回最大平面大小。

DRM_CAP_CURSOR_HEIGHT

DRM_CAP_CURSOR_HEIGHT

描述

请参阅 DRM_CAP_CURSOR_WIDTH

DRM_CAP_ADDFB2_MODIFIERS

DRM_CAP_ADDFB2_MODIFIERS

描述

如果设置为 1,驱动程序支持在 DRM_IOCTL_MODE_ADDFB2 ioctl 中提供修饰符。

DRM_CAP_PAGE_FLIP_TARGET

DRM_CAP_PAGE_FLIP_TARGET

描述

如果设置为 1,驱动程序支持 DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTEDRM_MODE_PAGE_FLIP_TARGET_RELATIVE 标志,用于 drm_mode_crtc_page_flip_target.flags,用于 DRM_IOCTL_MODE_PAGE_FLIP ioctl。

DRM_CAP_CRTC_IN_VBLANK_EVENT

DRM_CAP_CRTC_IN_VBLANK_EVENT

描述

如果设置为 1,内核支持在 drm_event_vblank.crtc_id 中为 DRM_EVENT_VBLANKDRM_EVENT_FLIP_COMPLETE 事件报告 CRTC ID。

从内核版本 4.12 开始,此功能始终设置为 1。

DRM_CAP_SYNCOBJ

DRM_CAP_SYNCOBJ

描述

如果设置为 1,则驱动程序支持同步对象。请参阅 DRM 同步对象

DRM_CAP_SYNCOBJ_TIMELINE

DRM_CAP_SYNCOBJ_TIMELINE

描述

如果设置为 1,则驱动程序支持同步对象上的时间线操作。请参阅 DRM 同步对象

DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP

DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP

描述

如果设置为 1,则驱动程序支持用于原子提交的 DRM_MODE_PAGE_FLIP_ASYNC

DRM_CLIENT_CAP_STEREO_3D

DRM_CLIENT_CAP_STEREO_3D

描述

如果设置为 1,DRM 核心将通过在 struct drm_mode_modeinfo 的标志中通告支持的 3D 布局来公开监视器的立体 3D 功能。请参阅 DRM_MODE_FLAG_3D_*

从内核版本 3.13 开始,所有驱动程序始终支持此功能。

DRM_CLIENT_CAP_UNIVERSAL_PLANES

DRM_CLIENT_CAP_UNIVERSAL_PLANES

描述

如果设置为 1,DRM 核心将向用户空间公开所有平面(叠加、主平面和光标)。

此功能已在内核版本 3.15 中引入。从内核版本 3.17 开始,所有驱动程序始终支持此功能。

DRM_CLIENT_CAP_ATOMIC

DRM_CLIENT_CAP_ATOMIC

描述

如果设置为 1,DRM 核心将向用户空间公开原子属性。这隐式启用了 DRM_CLIENT_CAP_UNIVERSAL_PLANESDRM_CLIENT_CAP_ASPECT_RATIO

如果驱动程序不支持原子模式设置,则启用此功能将失败,并显示 -EOPNOTSUPP。

此功能已在内核版本 4.0 中引入。从内核版本 4.2 开始,原子驱动程序始终支持此功能。

DRM_CLIENT_CAP_ASPECT_RATIO

DRM_CLIENT_CAP_ASPECT_RATIO

描述

如果设置为 1,DRM 核心将在模式中提供纵横比信息。请参阅 DRM_MODE_FLAG_PIC_AR_*

从内核版本 4.18 开始,所有驱动程序始终支持此功能。

DRM_CLIENT_CAP_WRITEBACK_CONNECTORS

DRM_CLIENT_CAP_WRITEBACK_CONNECTORS

描述

如果设置为 1,DRM 核心将公开特殊的连接器,用于在提交时将场景设置写回内存。客户端必须首先启用 DRM_CLIENT_CAP_ATOMIC

从内核版本 4.19 开始,支持原子操作的驱动程序始终支持此功能。

DRM_CLIENT_CAP_CURSOR_PLANE_HOTSPOT

DRM_CLIENT_CAP_CURSOR_PLANE_HOTSPOT

描述

用于准虚拟化硬件(例如 vmwgfx、qxl、virtio 和 virtualbox)的驱动程序对光标平面有额外的限制(因此使得这些驱动程序上的光标平面不是真正的通用),例如,它们需要光标平面的行为类似于鼠标光标,并且具有正确设置的热点属性。如果未设置此客户端功能,则 DRM 核心将隐藏这些虚拟化驱动程序上的光标平面,因为不设置它意味着客户端无法处理这些额外的限制。设置光标热点并将光标平面视为鼠标光标的客户端应设置此属性。客户端必须首先启用 DRM_CLIENT_CAP_ATOMIC

在不特殊处理光标平面的驱动程序(即非虚拟化驱动程序)上设置此属性将返回 EOPNOTSUPP,用户空间可以使用该返回值来衡量他们运行的硬件/驱动程序的要求。

从内核版本 6.6 开始,支持原子操作的虚拟化驱动程序始终支持此功能。

struct drm_syncobj_eventfd

定义:

struct drm_syncobj_eventfd {
    __u32 handle;
    __u32 flags;
    __u64 point;
    __s32 fd;
    __u32 pad;
};

成员

handle

syncobj 句柄。

flags

设置为 0 以等待点被信号通知,或设置为 DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE 以等待栅栏可用于该点。

point

syncobj 时间线点(对于二进制 syncobj,设置为零)。

fd

要将事件发送到的现有 eventfd。

pad

必须为零。

描述

注册一个 eventfd,以便通过 syncobj 发出信号。eventfd 计数器将递增 1。

DRM_IOCTL_GEM_CLOSE

DRM_IOCTL_GEM_CLOSE

关闭 GEM 句柄。

描述

内核不使用引用计数来管理 GEM 句柄。用户空间负责管理它们的生命周期。例如,如果用户空间在同一个 DRM 文件描述符上两次导入同一个内存对象,则两次导入都会返回相同的 GEM 句柄,并且用户空间需要确保 DRM_IOCTL_GEM_CLOSE 仅执行一次。当分配内存对象,然后将其导出并在同一个 DRM 文件描述符上再次导入时,也会发生相同的情况。DRM_IOCTL_MODE_GETFB2 IOCTL 是一个例外,即使在执行 IOCTL 之前,已存在的 GEM 句柄已引用相同的内存对象,它始终会返回全新的 GEM 句柄。

DRM_IOCTL_PRIME_HANDLE_TO_FD

DRM_IOCTL_PRIME_HANDLE_TO_FD

将 GEM 句柄转换为 DMA-BUF FD。

描述

用户空间使用要导出的 GEM 句柄设置 drm_prime_handle.handledrm_prime_handle.flags,并在 drm_prime_handle.fd 中获取 DMA-BUF 文件描述符。

导出可能会因任何特定于驱动程序的原因而失败,例如,因为此特定 GEM 句柄不支持导出(但可能支持其他句柄)。

通过 DRM_PRIME_CAP_EXPORT 通告对导出 DMA-BUF 的支持。

DRM_IOCTL_PRIME_FD_TO_HANDLE

DRM_IOCTL_PRIME_FD_TO_HANDLE

将 DMA-BUF FD 转换为 GEM 句柄。

描述

用户空间使用要导入的 DMA-BUF 文件描述符设置 drm_prime_handle.fd,并在 drm_prime_handle.handle 中获取 GEM 句柄。drm_prime_handle.flags 未使用。

如果现有 GEM 句柄引用了支持 DMA-BUF 的内存对象,则会返回该 GEM 句柄。因此,需要处理任意 DMA-BUF 的用户空间必须具有用户空间查找数据结构,以手动引用计数重复的 GEM 句柄。有关更多信息,请参见 DRM_IOCTL_GEM_CLOSE

导入可能会因任何特定于驱动程序的原因而失败,例如,因为仅支持在此 DRM 设备上分配的 DMA-BUF 进行导入。

通过 DRM_PRIME_CAP_IMPORT 通告对导入 DMA-BUF 的支持。

DRM_IOCTL_MODE_RMFB

DRM_IOCTL_MODE_RMFB

删除帧缓冲。

描述

这将删除先前通过 ADDFB/ADDFB2 添加的帧缓冲。IOCTL 参数是帧缓冲对象 ID。

警告:删除当前在启用的平面上使用的帧缓冲将禁用该平面。与该平面链接的 CRTC 也可能会被禁用(取决于驱动程序的功能)。

DRM_IOCTL_MODE_CREATE_DUMB

DRM_IOCTL_MODE_CREATE_DUMB

创建新的哑缓冲区对象。

描述

KMS 哑缓冲区提供了一种非常原始的方法来分配适合扫描输出的缓冲区对象并将其映射以进行软件渲染。KMS 哑缓冲区不适用于硬件加速渲染或视频解码。KMS 哑缓冲区不适合在分配它们的 KMS 设备以外的任何其他设备上显示。另请参见 哑缓冲区对象

IOCTL 参数是 struct drm_mode_create_dumb

用户空间应通过此 IOCTL 创建 KMS 哑缓冲区,然后通过 DRM_IOCTL_MODE_ADDFB 将其添加为 KMS 帧缓冲,并通过 DRM_IOCTL_MODE_MAP_DUMB 将其映射。

DRM_CAP_DUMB_BUFFER 指示是否支持此 IOCTL。DRM_CAP_DUMB_PREFERRED_DEPTHDRM_CAP_DUMB_PREFER_SHADOW 指示驱动程序对哑缓冲区的首选项。

DRM_IOCTL_MODE_GETFB2

DRM_IOCTL_MODE_GETFB2

获取帧缓冲元数据。

描述

这将查询有关帧缓冲的元数据。用户空间将 drm_mode_fb_cmd2.fb_id 填写为输入,而内核将结构的其余部分填写为输出。

如果客户端是 DRM 主设备或具有 CAP_SYS_ADMIN,则 drm_mode_fb_cmd2.handles 将填充 GEM 缓冲区句柄。始终返回全新的 GEM 句柄,即使在 DRM 文件描述符上已存在引用同一内存对象的另一个 GEM 句柄。调用者负责删除新句柄,例如通过 DRM_IOCTL_GEM_CLOSE IOCTL。如果多个平面使用相同的内存对象,则会为它们返回相同的新句柄。平面是有效的,直到有一个句柄为零 -- 这可以用于计算平面的数量。

否则,drm_mode_fb_cmd2.handles 将被置零,并且平面是有效的,直到有一个平面的 drm_mode_fb_cmd2.pitches 为零。

如果帧缓冲具有格式修饰符,则 DRM_MODE_FB_MODIFIERS 将在 drm_mode_fb_cmd2.flags 中设置,并且 drm_mode_fb_cmd2.modifier 将包含修饰符。否则,用户空间必须忽略 drm_mode_fb_cmd2.modifier

为了在不泄漏 GEM 句柄的情况下获取每个平面的 DMA-BUF FD,用户空间可以通过 DRM_IOCTL_PRIME_HANDLE_TO_FD 导出每个句柄,然后立即通过 DRM_IOCTL_GEM_CLOSE 关闭每个唯一的句柄,并确保不重复关闭数组中多次指定的句柄。

DRM_IOCTL_MODE_CLOSEFB

DRM_IOCTL_MODE_CLOSEFB

关闭帧缓冲。

描述

这将关闭先前通过 ADDFB/ADDFB2 添加的帧缓冲。IOCTL 参数是帧缓冲对象 ID。

此 IOCTL 与 DRM_IOCTL_MODE_RMFB 类似,但它不会禁用平面和 CRTC。只要帧缓冲被平面使用,它就会保持活动状态。当平面不再使用该帧缓冲(因为该帧缓冲被另一个帧缓冲替换,或者该平面被禁用)时,该帧缓冲将被清理。

这对于实现两个进程之间的无闪烁过渡非常有用。

根据威胁模型,用户空间可能需要确保帧缓冲不暴露任何敏感的用户信息:附加到平面的已关闭帧缓冲可能会被下一个 DRM 主设备读取。

DRM_IOCTL_SET_CLIENT_NAME

DRM_IOCTL_SET_CLIENT_NAME

为 drm_file 附加一个名称

描述

拥有名称可以更轻松地进行跟踪和调试。名称的长度(不包括空终止符)必须 <= DRM_CLIENT_NAME_MAX_LEN。如果名称包含空格或不可打印字符,则调用将失败。

struct drm_event

DRM 事件的头

定义:

struct drm_event {
    __u32 type;
    __u32 length;
};

成员

type

事件类型。

length

有效负载字节总数(包括头)。

描述

此结构是在 DRM FD 上写回用户空间的事件的头。在 DRM FD 上读取将始终只返回完整的事件:例如,如果读取缓冲区为 100 字节大小,并且有两个 64 字节的事件挂起,则只会返回一个事件。

事件类型 0 - 0x7fffffff 是通用的 DRM 事件,0x80000000 及以上是特定于芯片组的。通用的 DRM 事件包括 DRM_EVENT_VBLANKDRM_EVENT_FLIP_COMPLETEDRM_EVENT_CRTC_SEQUENCE

DRM_EVENT_VBLANK

DRM_EVENT_VBLANK

垂直消隐事件

描述

此事件是响应 DRM_IOCTL_WAIT_VBLANK 并设置 _DRM_VBLANK_EVENT 标志而发送的。

事件有效负载是一个结构体 drm_event_vblank。

DRM_EVENT_FLIP_COMPLETE

DRM_EVENT_FLIP_COMPLETE

页面翻转完成事件

描述

此事件是响应原子提交或设置了 DRM_MODE_PAGE_FLIP_EVENT 标志的传统页面翻转而发送的。

事件有效负载是一个结构体 drm_event_vblank。

DRM_EVENT_CRTC_SEQUENCE

DRM_EVENT_CRTC_SEQUENCE

CRTC 序列事件

描述

此事件是响应 DRM_IOCTL_CRTC_QUEUE_SEQUENCE 而发送的。

事件有效负载是一个结构体 drm_event_crtc_sequence。

struct drm_mode_modeinfo

显示模式信息。

定义:

struct drm_mode_modeinfo {
    __u32 clock;
    __u16 hdisplay;
    __u16 hsync_start;
    __u16 hsync_end;
    __u16 htotal;
    __u16 hskew;
    __u16 vdisplay;
    __u16 vsync_start;
    __u16 vsync_end;
    __u16 vtotal;
    __u16 vscan;
    __u32 vrefresh;
    __u32 flags;
    __u32 type;
    char name[DRM_DISPLAY_MODE_LEN];
};

成员

clock

像素时钟,单位为 kHz

hdisplay

水平显示大小

hsync_start

水平同步开始

hsync_end

水平同步结束

htotal

水平总大小

hskew

水平偏移

vdisplay

垂直显示大小

vsync_start

垂直同步开始

vsync_end

垂直同步结束

vtotal

垂直总大小

vscan

垂直扫描

vrefresh

近似垂直刷新率,单位为 Hz

flags

杂项标志的位掩码,请参见 DRM_MODE_FLAG_* 定义

type

类型标志的位掩码,请参见 DRM_MODE_TYPE_* 定义

name

描述模式分辨率的字符串

描述

这是用户空间 API 显示模式信息结构。有关内核版本,请参见 struct drm_display_mode

struct drm_mode_get_plane

获取平面元数据。

定义:

struct drm_mode_get_plane {
    __u32 plane_id;
    __u32 crtc_id;
    __u32 fb_id;
    __u32 possible_crtcs;
    __u32 gamma_size;
    __u32 count_format_types;
    __u64 format_type_ptr;
};

成员

plane_id

应检索其信息的平面的对象 ID。由调用者设置。

crtc_id

当前 CRTC 的对象 ID。

fb_id

当前 fb 的对象 ID。

possible_crtcs

与平面兼容的 CRTC 的位掩码。创建 CRTC 时,会为其分配一个索引,该索引对应于其在位掩码中的位置。位 N 对应于 CRTC 索引 N。

gamma_size

从未使用过。

count_format_types

格式的数量。

format_type_ptr

指向平面支持的格式 __u32 数组的指针。这些格式不需要修饰符。

描述

用户空间可以执行 GETPLANE ioctl 以检索有关平面的信息。

要检索支持的格式数量,请将 count_format_types 设置为零并调用 ioctl。count_format_types 将使用该值进行更新。

要检索这些格式,请分配一个内存数组,该内存足以存储 count_format_types 格式。将 format_type_ptr 指向此数组,然后再次调用 ioctl(其中 count_format_types 仍设置为第一次 ioctl 调用中返回的值)。

struct drm_mode_get_connector

获取连接器元数据。

定义:

struct drm_mode_get_connector {
    __u64 encoders_ptr;
    __u64 modes_ptr;
    __u64 props_ptr;
    __u64 prop_values_ptr;
    __u32 count_modes;
    __u32 count_props;
    __u32 count_encoders;
    __u32 encoder_id;
    __u32 connector_id;
    __u32 connector_type;
    __u32 connector_type_id;
    __u32 connection;
    __u32 mm_width;
    __u32 mm_height;
    __u32 subpixel;
    __u32 pad;
};

成员

encoders_ptr

指向 __u32 对象 ID 数组的指针。

modes_ptr

指向 struct drm_mode_modeinfo 数组的指针。

props_ptr

指向 __u32 属性 ID 数组的指针。

prop_values_ptr

指向 __u64 属性值数组的指针。

count_modes

模式数量。

count_props

属性数量。

count_encoders

编码器数量。

encoder_id

当前编码器的对象 ID。

connector_id

连接器的对象 ID。

connector_type

连接器的类型。

请参见 DRM_MODE_CONNECTOR_* 定义。

connector_type_id

特定于类型的连接器编号。

这不是一个对象 ID。这是一个按类型划分的连接器编号。每个 (type, type_id) 组合在 DRM 设备的所有连接器中都是唯一的。

(type, type_id) 组合不是一个稳定的标识符:type_id 可能会根据驱动程序探测顺序而变化。

connection

连接器的状态。

请参见 enum drm_connector_status

mm_width

连接的接收器的宽度,单位为毫米。

mm_height

连接的接收器的高度,单位为毫米。

subpixel

连接的接收器的子像素顺序。

请参见枚举 subpixel_order。

pad

填充,必须为零。

描述

用户空间可以执行 GETCONNECTOR ioctl 以检索有关连接器的信息。用户空间应至少执行两次此 ioctl 以检索编码器、模式和属性:第一次检索元素数量,第二次检索元素本身。

要检索元素数量,请将 count_propscount_encoders 设置为零,将 count_modes 设置为 1,并将 modes_ptr 设置为临时的 struct drm_mode_modeinfo 元素。

要检索元素,请为 encoders_ptrmodes_ptrprops_ptrprop_values_ptr 分配数组,然后将 count_modescount_propscount_encoders 设置为其容量。

仅执行两次 ioctl 可能存在竞争:在两次 ioctl 之间,元素的数量可能因热插拔事件而发生了变化。用户空间应重试最后一个 ioctl,直到元素的数量稳定为止。内核不会填充任何不具有预期长度的数组。

强制探测连接器

如果 count_modes 字段设置为零且 DRM 客户端是当前的 DRM 主设备,则内核将在连接器上执行强制探测,以刷新连接器状态、模式和 EDID。强制探测可能很慢,可能会导致闪烁,并且 ioctl 将会阻塞。

用户空间需要强制探测连接器,以确保其元数据在启动时和接收到热插拔事件后是最新的。当用户明确请求时,用户空间可以执行强制探测。在其他情况下,用户空间不应执行强制探测。

struct drm_mode_property_enum

枚举/位域条目的描述。

定义:

struct drm_mode_property_enum {
    __u64 value;
    char name[DRM_PROP_NAME_LEN];
};

成员

value

此枚举条目的数值。

name

此枚举条目的符号名称。

描述

有关详细信息,请参阅struct drm_property_enum

struct drm_mode_get_property

获取属性元数据。

定义:

struct drm_mode_get_property {
    __u64 values_ptr;
    __u64 enum_blob_ptr;
    __u32 prop_id;
    __u32 flags;
    char name[DRM_PROP_NAME_LEN];
    __u32 count_values;
    __u32 count_enum_blobs;
};

成员

values_ptr

指向 __u64 数组的指针。

enum_blob_ptr

指向 struct drm_mode_property_enum 数组的指针。

prop_id

应检索的属性的对象 ID。由调用者设置。

flags

DRM_MODE_PROP_* 位域。有关标志的定义,请参阅 drm_property.flags

name

符号属性名称。用户空间应使用此字段来识别属性。

count_values

values_ptr 中的元素数量。

count_enum_blobs

enum_blob_ptr 中的元素数量。

描述

用户空间可以执行 GETPROPERTY ioctl 来检索有关属性的信息。同一个属性可能会附加到多个对象,请参阅“模式设置基本对象抽象”。

values_ptr 字段的含义取决于属性类型。有关更多详细信息,请参阅 drm_property.flags

当属性的类型为 DRM_MODE_PROP_ENUMDRM_MODE_PROP_BITMASK 时,enum_blob_ptrcount_enum_blobs 字段才有意义。为了向后兼容,当属性的类型为 DRM_MODE_PROP_BLOB 时,内核始终会将 count_enum_blobs 设置为零。如果属性的类型不同,用户空间必须忽略这两个字段。

用户空间应至少执行两次此 ioctl 来检索值和枚举:第一次检索元素数量,第二次检索元素本身。

要检索元素数量,请将 count_valuescount_enum_blobs 设置为零,然后调用 ioctl。count_values 将更新为元素数量。如果属性的类型为 DRM_MODE_PROP_ENUMDRM_MODE_PROP_BITMASKcount_enum_blobs 也会被更新。

要检索元素本身,请为 values_ptr 分配一个数组,并将 count_values 设置为其容量。如果属性的类型为 DRM_MODE_PROP_ENUMDRM_MODE_PROP_BITMASK,请为 enum_blob_ptr 分配一个数组,并将 count_enum_blobs 设置为其容量。再次调用 ioctl 将填充数组。

struct drm_mode_fb_cmd2

帧缓冲元数据。

定义:

struct drm_mode_fb_cmd2 {
    __u32 fb_id;
    __u32 width;
    __u32 height;
    __u32 pixel_format;
    __u32 flags;
    __u32 handles[4];
    __u32 pitches[4];
    __u32 offsets[4];
    __u64 modifier[4];
};

成员

fb_id

帧缓冲的对象 ID。

width

帧缓冲的宽度。

height

帧缓冲的高度。

pixel_format

FourCC 格式代码,请参阅 drm_fourcc.h 中的 DRM_FORMAT_* 常量。

flags

帧缓冲标志(请参阅 DRM_MODE_FB_INTERLACEDDRM_MODE_FB_MODIFIERS)。

handles

GEM 缓冲区句柄,每个平面一个。如果未使用该平面,则设置为 0。同一句柄可用于多个平面。

pitches

以字节为单位的间距(也称为步幅),每个平面一个。

offsets

以字节为单位的缓冲区偏移量,每个平面一个。

modifier

格式修饰符,每个平面一个。请参阅 drm_fourcc.h 中的 DRM_FORMAT_MOD_* 常量。所有平面必须使用相同的修饰符。除非 flags 中设置了 DRM_MODE_FB_MODIFIERS,否则将被忽略。

描述

此结构体保存帧缓冲元数据。有两种使用方式:

  • 用户空间可以填充此结构体并执行 DRM_IOCTL_MODE_ADDFB2 ioctl 来注册新的帧缓冲。新的帧缓冲对象 ID 将由内核在 fb_id 中设置。

  • 用户空间可以设置 fb_id 并执行 DRM_IOCTL_MODE_GETFB2 ioctl 来获取有关现有帧缓冲的元数据。

对于平面格式,此结构体允许最多 4 个缓冲区对象,每个平面都有偏移量和间距。间距和偏移量顺序由 drm_fourcc.h 定义的格式 FourCC 决定,例如 NV12 描述为:

YUV 4:2:0 图像,其中包含一个 8 位 Y 样本的平面,后跟一个包含 8 位 2x2 子采样色差样本的交错 U/V 平面。

因此,它将由 offsets[0] 处的 Y 平面和 offsets[1] 处的 UV 平面组成。

为了适应平铺、压缩等格式,可以指定修饰符。有关更多信息,请参阅“格式修饰符”部分。请注意,即使看起来每个平面都有一个修饰符,但实际上并非如此。每个平面的修饰符必须相同。因此,多平面格式的不同数据布局的所有组合都必须作为单独的修饰符进行枚举。

当未使用时,handlespitchesoffsetsmodifier 中的所有条目都必须为零。警告,对于 offsetsmodifier,不能使用零来判断条目是否被使用,因为它是有效值(零偏移量很常见,零修饰符是 DRM_FORMAT_MOD_LINEAR)。

struct drm_plane_size_hint

平面大小提示

定义:

struct drm_plane_size_hint {
    __u16 width;
    __u16 height;
};

成员

width

平面以像素为单位的宽度

height

平面以像素为单位的高度

描述

平面 SIZE_HINTS 属性 blob 包含一个 struct drm_plane_size_hint 数组。

struct hdr_metadata_infoframe

HDR 元数据信息帧数据。

定义:

struct hdr_metadata_infoframe {
    __u8 eotf;
    __u8 metadata_type;
    struct {
        __u16 x, y;
    } display_primaries[3];
    struct {
        __u16 x, y;
    } white_point;
    __u16 max_display_mastering_luminance;
    __u16 min_display_mastering_luminance;
    __u16 max_cll;
    __u16 max_fall;
};

成员

eotf

流中使用的电光传输函数 (EOTF)。

metadata_type

Static_Metadata_Descriptor_ID。

display_primaries

数据的色度基色。这些被编码为 16 位无符号值,单位为 0.00002,其中 0x0000 表示零,0xC350 表示 1.0000。display_primaries.x:色度基色的 X 坐标。display_primaries.y:色度基色的 Y 坐标。

white_point

色彩空间数据的白点。这些被编码为 16 位无符号值,单位为 0.00002,其中 0x0000 表示零,0xC350 表示 1.0000。white_point.x:色度基色的白点 X 坐标。white_point.y:色度基色的白点 Y 坐标。

max_display_mastering_luminance

最大母带显示亮度。此值被编码为 16 位无符号值,单位为 1 cd/m2,其中 0x0001 表示 1 cd/m2,0xFFFF 表示 65535 cd/m2。

min_display_mastering_luminance

最小母带显示亮度。此值被编码为 16 位无符号值,单位为 0.0001 cd/m2,其中 0x0001 表示 0.0001 cd/m2,0xFFFF 表示 6.5535 cd/m2。

max_cll

最大内容光照强度级别。此值被编码为 16 位无符号值,单位为 1 cd/m2,其中 0x0001 表示 1 cd/m2,0xFFFF 表示 65535 cd/m2。

max_fall

最大帧平均光照强度级别。此值被编码为 16 位无符号值,单位为 1 cd/m2,其中 0x0001 表示 1 cd/m2,0xFFFF 表示 65535 cd/m2。

描述

符合 CTA 861.G 规范的 HDR 元数据信息帧。预计与规范完全匹配。

用户空间应根据此结构体中描述的格式传递元数据信息。

struct hdr_output_metadata

HDR 输出元数据

定义:

struct hdr_output_metadata {
    __u32 metadata_type;
    union {
        struct hdr_metadata_infoframe hdmi_metadata_type1;
    };
};

成员

metadata_type

Static_Metadata_Descriptor_ID。

{unnamed_union}

anonymous

hdmi_metadata_type1

HDR 元数据信息帧。

描述

要从用户空间传递的元数据信息

DRM_MODE_PAGE_FLIP_EVENT

DRM_MODE_PAGE_FLIP_EVENT

描述

请求内核在页面翻转完成后,发送回类型为 DRM_EVENT_FLIP_COMPLETE 的垂直同步事件(请参阅 struct drm_event_vblank)。

DRM_MODE_PAGE_FLIP_ASYNC

DRM_MODE_PAGE_FLIP_ASYNC

描述

请求尽快执行页面翻转,即不因等待垂直同步而延迟。这可能会导致屏幕上出现撕裂。

与原子 uAPI 一起使用时,如果硬件不支持对此更新执行异步页面翻转,则驱动程序将返回错误。用户空间应处理此情况,例如,通过回退到常规页面翻转。

请注意,某些硬件可能需要执行最后一次同步页面翻转,然后才能切换到异步页面翻转。作为例外,即使第一次页面翻转不是异步的,驱动程序也会返回成功。

DRM_MODE_PAGE_FLIP_FLAGS

DRM_MODE_PAGE_FLIP_FLAGS

描述

适用于 drm_mode_crtc_page_flip_target.flags 的标志位掩码。

struct drm_mode_create_dumb

创建一个用于扫描输出的 KMS 哑缓冲区。

定义:

struct drm_mode_create_dumb {
    __u32 height;
    __u32 width;
    __u32 bpp;
    __u32 flags;
    __u32 handle;
    __u32 pitch;
    __u64 size;
};

成员

height

以像素为单位的缓冲区高度

width

以像素为单位的缓冲区宽度

bpp

每个像素的位数

flags

必须为零

handle

缓冲区对象句柄

pitch

两条连续线之间的字节数

size

整个缓冲区的大小(以字节为单位)

描述

用户空间填充 heightwidthbppflags。如果 IOCTL 成功,则内核填充 handlepitchsize

DRM_MODE_ATOMIC_TEST_ONLY

DRM_MODE_ATOMIC_TEST_ONLY

描述

不要应用原子提交,而是检查硬件是否支持此配置。

有关仅测试提交的更多详细信息,请参阅 drm_mode_config_funcs.atomic_check

DRM_MODE_ATOMIC_NONBLOCK

DRM_MODE_ATOMIC_NONBLOCK

描述

在应用原子提交时不阻塞。 DRM_IOCTL_MODE_ATOMIC IOCTL 立即返回,而不是等待硬件应用更改。请注意,驱动程序仍然会检查更新是否可以在返回之前应用。

DRM_MODE_ATOMIC_ALLOW_MODESET

DRM_MODE_ATOMIC_ALLOW_MODESET

描述

允许更新在应用过程中导致临时或瞬态可见伪影。应用更新也可能比页面翻转花费更多时间。所有视觉伪影将在更新完成后消失,这通过垂直消隐事件的时间戳发出信号(请参阅结构 drm_event_vblank)。

当 KMS 更新可能导致可见伪影时,必须设置此标志。如果没有此标志,此类 KMS 更新将返回 EINVAL 错误。哪种更新可能导致可见伪影取决于驱动程序和硬件。用户空间需要预先知道更新是否可能导致可见伪影,可以使用 DRM_MODE_ATOMIC_TEST_ONLY 而不使用 DRM_MODE_ATOMIC_ALLOW_MODESET 来查看是否失败。

在驱动程序所知的范围内,当未设置此标志时,保证不会出现视觉伪影。某些接收器可能会显示驱动程序无法控制的视觉伪影。

DRM_MODE_ATOMIC_FLAGS

DRM_MODE_ATOMIC_FLAGS

描述

DRM_IOCTL_MODE_ATOMIC IOCTL 在 drm_mode_atomic.flags 中接受的标志的位字段。

struct drm_mode_create_blob

创建新的 blob 属性

定义:

struct drm_mode_create_blob {
    __u64 data;
    __u32 length;
    __u32 blob_id;
};

成员

data

要复制的数据的指针。

length

要复制的数据的长度。

blob_id

返回:新的属性 ID。

描述

创建一个新的“blob”数据属性,从数据指针复制长度字节,并返回新的 blob ID。

struct drm_mode_destroy_blob

销毁用户 blob

定义:

struct drm_mode_destroy_blob {
    __u32 blob_id;
};

成员

blob_id

要销毁的 blob_id

描述

销毁用户创建的 blob 属性。

用户空间可以在不需要通过其 blob 对象 ID 引用 blob 时立即释放它们。例如,如果您在原子提交中使用 MODE_ID blob,并且您不会进行另一个重用相同 ID 的提交,则可以在发出提交后立即销毁该 blob,而无需等待它完成。

struct drm_mode_create_lease

创建租约

定义:

struct drm_mode_create_lease {
    __u64 object_ids;
    __u32 object_count;
    __u32 flags;
    __u32 lessee_id;
    __u32 fd;
};

成员

object_ids

对象 ID 数组的指针 (__u32)

object_count

对象 ID 的数量

flags

新 FD 的标志 (O_CLOEXEC 等)

lessee_id

返回:承租人的唯一标识符。

fd

返回:新 drm_master 文件的文件描述符

描述

租用模式资源,创建另一个 drm_master。

如果启用了 DRM_CLIENT_CAP_UNIVERSAL_PLANES,则 object_ids 数组必须至少引用一个 CRTC、一个连接器和一个平面。或者,租约可以完全为空。

struct drm_mode_list_lessees

列出租户

定义:

struct drm_mode_list_lessees {
    __u32 count_lessees;
    __u32 pad;
    __u64 lessees_ptr;
};

成员

count_lessees

承租人的数量。

在输入时,提供数组的长度。在输出时,提供总数。不会写回超过输入数字的数字,因此可以使用两次调用来获取大小,然后获取数据。

pad

填充。

lessees_ptr

承租人的指针。

承租人 ID 的 __u64 数组的指针

描述

从 drm_master 列出承租人。

struct drm_mode_get_lease

获取租约

定义:

struct drm_mode_get_lease {
    __u32 count_objects;
    __u32 pad;
    __u64 objects_ptr;
};

成员

count_objects

租用对象的数量。

在输入时,提供数组的长度。在输出时,提供总数。不会写回超过输入数字的数字,因此可以使用两次调用来获取大小,然后获取数据。

pad

填充。

objects_ptr

对象的指针。

对象 ID 的 __u32 数组的指针。

描述

获取租用的对象。

struct drm_mode_revoke_lease

撤销租约

定义:

struct drm_mode_revoke_lease {
    __u32 lessee_id;
};

成员

lessee_id

承租人的唯一 ID

struct drm_mode_rect

二维矩形。

定义:

struct drm_mode_rect {
    __s32 x1;
    __s32 y1;
    __s32 x2;
    __s32 y2;
};

成员

x1

水平起始坐标(包含)。

y1

垂直起始坐标(包含)。

x2

水平结束坐标(不包含)。

y2

垂直结束坐标(不包含)。

描述

由于 drm 子系统使用 struct drm_rect 来管理矩形区域,因此将其导出到用户空间。

目前由 drm_mode_atomic blob 属性 FB_DAMAGE_CLIPS 使用。

struct drm_mode_closefb

定义:

struct drm_mode_closefb {
    __u32 fb_id;
    __u32 pad;
};

成员

fb_id

帧缓冲 ID。

pad

必须为零。

dma-buf 互操作性

有关 dma-buf 如何在 DRM 中集成和公开的信息,请参阅 交换像素缓冲区