drm api简明操作(一)直接送显

本文介绍了DRM架构的组成部分,包括FrameBuffer、Plane、CRTC、Encoder和Connector,并详细阐述了如何使用DRM API进行显示资源获取、连接器选择、创建FB、映射缓冲区以及设置显示模式的过程。在实际应用中,通常需要两个缓冲区交替使用以避免显示同步刷新的问题。
摘要由CSDN通过智能技术生成

一. 概念

贴一张图(这张图可能和其他地方的不一样,我作了修改,后文会解释):
在这里插入图片描述
DRM架构包含如上图所示的几个部分,显示一张图像,就是分别获取上面的各个节点信息,进行配置,将将fb -> planes -> crtc -> encoder - > connector连接起来 ,最终实现把FB的内容推送到显示器显示的目的。

1.1 FrameBuffer帧缓存

FB是图像实际存放的一段内存区域,是我们想要显示的原始图像所在空间,一般存放的是RGBX或者YUV的图像数据。这些数据可能是虚拟地址空间或者DMA、CMA等内存区域,和显示模组没有硬件关系。

1.2 Plane图层

显示的基本单元,每个图层可能关联一个FB的数据。图层是显示模组硬件,每个图层叠加顺序、支持的透明度等一般是硬件决定的,如果超过图层数量限制就需要软件来额外处理。

注:
很多示例图上是把FB和Planes分开的输入到CRTC的,但我理解,所有要显示的FB都必须要依赖到一个图层才能显示,除非CRTC本身有一个背景层,这个背景层不能叫plane,其它在此基础上做透明叠加等操作的额外图层才能叫Plane???而现在通用的显示控制器一般是可以自由设定图层顺序和透明度的,每个plane可能是等效的,可以分别配置z-order来随意叠加,所以我是把所有FB直接指向了planes。如有错误请指正。

1.3 CRTC 扫描(CRT)控制器

把一个或者多个图层的数据作处理,形成视觉上的一张图像。比如有两个图层,一个是播放文件的视频图层,另一个是UI操作图层,将其叠加为一个新的图,送到下一级(Encoder)作显示。使用CRT猜测是沿用旧时的称呼。

1.4 Encoder 编码器

将CRTC生成的最终画面转化为不同的显示信号。

1.5 Connector连接器

将信号传送到显示器。

2. API简述

drm用户态接口是依赖于libdrm,因此需要先编译安装该库文件。使用libdrm来显示的主要api如下。

2.1 获取显示资源drmModeGetResources

	drmModeRes *res;
	int drm_fd;
	drm_fd = open("/dev/dri/card0", O_RDWR | O_CLOEXEC);
	res = drmModeGetResources(fd);
DRM(Direct Rendering Manager)是Linux内核中的一个子系统,它提供了一种机制,允许用户空间应用程序直接访问图形硬件。在DRM中,显示器的显示被表示为一个帧缓冲区,它是一个二维数组,其中每个元素表示一个像素的颜色值。帧缓冲区可以包含不同的像素格式,其中之一是NV12。 要在DRM中显示NV12数据,您需要使用DRM APIdrmModeAddFB2函数创建一个新的帧缓冲区对象,并将NV12数据附加到该对象。以下是一个简单的示例程序,演示如何使用DRM API显示NV12数据: ```c #include <fcntl.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <drm/drm_fourcc.h> #include <drm/drm_mode.h> #define WIDTH 640 #define HEIGHT 480 int main(int argc, char **argv) { int fd, ret; fd = open("/dev/dri/card0", O_RDWR); if (fd < 0) { fprintf(stderr, "failed to open DRM device\n"); return 1; } uint32_t handles[4] = { 0 }; uint32_t pitches[4] = { 0 }; uint32_t offsets[4] = { 0 }; uint64_t modifier = DRM_FORMAT_MOD_NONE; struct drm_mode_create_dumb create = { .width = WIDTH, .height = HEIGHT, .bpp = 16, }; struct drm_mode_map_dumb map = { 0 }; struct drm_mode_fb_cmd2 cmd = { 0 }; uint8_t *src, *dst; ret = ioctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &create); if (ret < 0) { fprintf(stderr, "failed to create dumb buffer: %m\n"); goto out_close; } cmd.width = WIDTH; cmd.height = HEIGHT; cmd.pixel_format = DRM_FORMAT_NV12; cmd.flags = DRM_MODE_FB_MODIFIERS; cmd.handles[0] = create.handle; cmd.pitches[0] = create.pitch; cmd.modifier[0] = modifier; ret = ioctl(fd, DRM_IOCTL_MODE_ADDFB2, &cmd); if (ret < 0) { fprintf(stderr, "failed to add framebuffer: %m\n"); goto out_destroy; } map.handle = create.handle; ret = ioctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &map); if (ret < 0) { fprintf(stderr, "failed to map dumb buffer: %m\n"); goto out_rmfb; } src = malloc(WIDTH * HEIGHT * 3 / 2); dst = mmap(NULL, create.size, PROT_WRITE, MAP_SHARED, fd, map.offset); if (dst == MAP_FAILED) { fprintf(stderr, "failed to mmap framebuffer: %m\n"); goto out_unmap; } /* fill NV12 buffer with some data */ for (int y = 0; y < HEIGHT; y++) { for (int x = 0; x < WIDTH; x++) { src[y * WIDTH + x] = x + y; } } for (int y = 0; y < HEIGHT / 2; y++) { for (int x = 0; x < WIDTH; x += 2) { src[WIDTH * HEIGHT + y * WIDTH + x] = y; src[WIDTH * HEIGHT + y * WIDTH + x + 1] = y + 128; } } /* copy NV12 buffer to framebuffer */ for (int y = 0; y < HEIGHT; y++) { memcpy(dst + y * create.pitch, src + y * WIDTH, WIDTH); } for (int y = 0; y < HEIGHT / 2; y++) { memcpy(dst + create.pitch * (HEIGHT + y), src + WIDTH * HEIGHT + y * WIDTH, WIDTH); } munmap(dst, create.size); free(src); close(fd); return 0; out_unmap: munmap(dst, create.size); out_rmfb: ioctl(fd, DRM_IOCTL_MODE_RMFB, &cmd.fb_id); out_destroy: ioctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &create); out_close: close(fd); return 1; } ``` 此程序使用DRM API创建一个NV12格式的帧缓冲区对象,并将其映射到用户空间。然后,它填充一个NV12格式的缓冲区,将其复制到帧缓冲区中,并清理所有资源。注意,此程序仅用于演示目的,不应在生产环境中使用。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值