DRM 从app到libdrm,到/dev/dri/card0

`libdrm` 是用户空间与 Linux 内核 DRM(Direct Rendering Manager)子系统之间的桥梁。它提供了一组 API,允许用户空间程序(如显示服务器、图形库)与内核 DRM 驱动进行交互,从而管理图形硬件资源(如显存、显示模式、渲染等)。

以下是 `libdrm` 和内核 DRM 驱动对接的详细说明:

## 1. **DRM 子系统概述**
DRM 是 Linux 内核中用于管理图形硬件的子系统,主要负责:
- 显存管理(如分配、释放)。
- 显示模式设置(如分辨率、刷新率)。
- 渲染和合成(如 2D/3D 加速)。
- 电源管理(如 GPU 频率调节)。

`libdrm` 是用户空间与 DRM 子系统交互的库,封装了与 DRM 驱动的通信细节。

## 2. **libdrm 和内核 DRM 驱动的对接流程**

### 2.1 **打开 DRM 设备**
用户空间程序通过 `libdrm` 打开 DRM 设备文件(如 `/dev/dri/card0`),获取文件描述符。#### 示例代码

#include <xf86drm.h>

int fd = drmOpen("card0", NULL);
if (fd < 0) {
    fprintf(stderr, "Failed to open DRM device\n");
    return -1;
}

- `drmOpen` 是 `libdrm` 提供的函数,用于打开 DRM 设备。
- 返回的文件描述符 `fd` 用于后续的 DRM API 调用。

### 2.2 **获取 DRM 资源**
通过 `libdrm` 获取 DRM 设备的资源信息,如 CRTC、Connector、Encoder 和 Framebuffer。#### 示例代码


#include <xf86drmMode.h>

drmModeRes *resources = drmModeGetResources(fd);
if (!resources) {
    fprintf(stderr, "Failed to get DRM resources\n");
    return -1;
}

// 遍历 CRTC、Connector 等资源
for (int i = 0; i < resources->count_crtcs; i++) {
    printf("CRTC %d: %d\n", i, resources->crtcs[i]);
}

drmModeFreeResources(resources);

- `drmModeGetResources` 获取 DRM 设备的资源信息。
- `drmModeFreeResources` 释放资源。

### 2.3 **设置显示模式**
通过 `libdrm` 设置显示模式(如分辨率、刷新率)。#### 示例代码

drmModeConnector *connector = drmModeGetConnector(fd, connector_id);
if (!connector) {
    fprintf(stderr, "Failed to get connector\n");
    return -1;
}
// 选择第一个显示模式
drmModeModeInfo *mode = &connector->modes[0];
// 设置 CRTC
int ret = drmModeSetCrtc(fd, crtc_id, fb_id, 0, 0, &connector_id, 1, mode);
if (ret < 0) {
    fprintf(stderr, "Failed to set CRTC\n");
    return -1;
}

drmModeFreeConnector(connector);

- `drmModeGetConnector` 获取连接器(如 HDMI、DP)的信息。
- `drmModeSetCrtc` 设置 CRTC 的显示模式。

### 2.4 **分配和管理显存**
通过 `libdrm` 分配和管理显存(Framebuffer)。

#### 示例代码

#include <drm_fourcc.h>

uint32_t fb_id;
uint32_t handles[4] = {0};
uint32_t pitches[4] = {0};
uint32_t offsets[4] = {0};

// 创建 Framebuffer
int ret = drmModeAddFB2(fd, width, height, DRM_FORMAT_XRGB8888,
                        handles, pitches, offsets, &fb_id, 0);
if (ret < 0) {
    fprintf(stderr, "Failed to create framebuffer\n");
    return -1;
}

// 使用 Framebuffer
ret = drmModeSetCrtc(fd, crtc_id, fb_id, 0, 0, &connector_id, 1, mode);
if (ret < 0) {
    fprintf(stderr, "Failed to set CRTC with framebuffer\n");
    return -1;
}
```

- `drmModeAddFB2` 创建一个 Framebuffer。
- `drmModeSetCrtc` 将 Framebuffer 绑定到 CRTC。

### 2.5 **处理 DRM 事件**
通过 `libdrm` 处理 DRM 事件(如 VBlank、Page Flip)。#### 示例代码

drmEventContext evctx = {0};
evctx.version = DRM_EVENT_CONTEXT_VERSION;
evctx.page_flip_handler = handle_page_flip;

while (1) {
    fd_set fds;
    FD_ZERO(&fds);
    FD_SET(fd, &fds);

    int ret = select(fd + 1, &fds, NULL, NULL, NULL);
    if (ret < 0) {
        fprintf(stderr, "select error\n");
        break;
    }

    if (FD_ISSET(fd, &fds)) {
        drmHandleEvent(fd, &evctx);
    }
}

- `drmHandleEvent` 处理 DRM 事件。
- `handle_page_flip` 是自定义的回调函数,用于处理 Page Flip 事件。

---

## 3. **内核 DRM 驱动的实现**
内核 DRM 驱动负责与硬件交互,实现以下功能:
- **设备初始化**:在 `probe` 函数中初始化硬件。
- **资源管理**:实现显存分配、释放等功能。
- **显示模式设置**:实现 CRTC、Encoder 和 Connector 的配置。
- **事件处理**:触发 VBlank、Page Flip 等事件。

#### 示例代码(内核模块)
```c
#include <drm/drmP.h>

static struct drm_driver my_driver = {
    .driver_features = DRIVER_MODESET | DRIVER_GEM,
    .load = my_driver_load,
    .unload = my_driver_unload,
    .gem_free_object = my_gem_free_object,
    .ioctls = my_ioctls,
    .fops = &my_fops,
};

static int __init my_driver_init(void)
{
    return drm_pci_init(&my_driver, &my_pci_driver);
}

static void __exit my_driver_exit(void)
{
    drm_pci_exit(&my_driver, &my_pci_driver);
}

module_init(my_driver_init);
module_exit(my_driver_exit);
```

- `my_driver_load`:初始化 DRM 设备。
- `my_gem_free_object`:释放 GEM 对象。
- `my_ioctls`:实现自定义的 IOCTL 接口。

---

## 4. **libdrm 和内核 DRM 驱动的交互**
-  主动调用,**IOCTL 接口**:
  - `libdrm` 通过 `ioctl` 系统调用与内核 DRM 驱动交互。
  - 内核 DRM 驱动实现了一系列 IOCTL 接口(如 `DRM_IOCTL_MODE_GETRESOURCES`、`DRM_IOCTL_MODE_SETCRTC`)。

- 主动调用 **GEM/TTM**:
  - `libdrm` 使用 GEM(Graphics Execution Manager)或 TTM(Translation Table Maps)管理显存。

- 被动触发,**事件机制**:
  - 内核 DRM 驱动通过事件机制(如 VBlank、Page Flip)通知用户空间。

---

## 5. **总结**
- `libdrm` 是用户空间与内核 DRM 驱动交互的库,封装了 DRM 设备的打开、资源管理、显存分配等功能。
- 内核 DRM 驱动负责与硬件交互,实现设备初始化、资源管理、显示模式设置等功能。
- 通过 `libdrm` 和内核 DRM 驱动的对接,用户空间程序可以高效地管理图形硬件资源。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值