dumb介绍
dumb buffer,一般是指CPU buffer,我们把这个buffer的内容填充,GPU只负责完整显示出来,GPU并不会对dumb buffer做任何加速。
关于dumb名字的由来,可以参照下面文章。
https://blog.csdn.net/hexiaolong2009/article/details/105961192
dumb buffer涉及三个主要操作, create, map, destroy。
dumb使用
dumb的create, map, destroy,三者都是通过drmIoctl调用的,而这个
/* create a dumb scanout buffer */
struct drm_mode_create_dumb {
__u32 height;
__u32 width;
__u32 bpp;
__u32 flags;
/* handle, pitch, size will be returned */
__u32 handle;
__u32 pitch;
__u64 size;
};
/* set up for mmap of a dumb scanout buffer */
struct drm_mode_map_dumb {
/** Handle for the object being mapped. */
__u32 handle;
__u32 pad;
/**
* Fake offset to use for subsequent mmap call
*
* This is a fixed-size type for 32/64 compatibility.
*/
__u64 offset;
};
struct drm_mode_destroy_dumb {
__u32 handle;
};
代码如下:
#include <errno.h>
#include <fcntl.h>
#include <memory.h>
#include <stdio.h>
#include <sys/mman.h>
#include <unistd.h>
#include <xf86drm.h>
static int test_dumb(int fd) {
struct drm_mode_create_dumb creq = {0};
struct drm_mode_destroy_dumb dreq = {0};
struct drm_mode_map_dumb mreq = {0};
int ret = 0;
/* create dumb buffer */
creq.width = 1920;
creq.height = 1080;
creq.bpp = 32;
ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &creq);
if (ret < 0) {
fprintf(stderr, "cannot create dumb buffer (%d): %m\n", errno);
return -errno;
}
printf("dumb created size=%llu, pitch=%d, handle=%d\n", creq.size, creq.pitch,
creq.handle);
/* prepare buffer for memory mapping */
mreq.handle = creq.handle;
ret = drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &mreq);
if (ret) {
fprintf(stderr, "cannot map dumb buffer (%d): %m\n", errno);
return -errno;
}
/* perform actual memory mapping */
uint8_t* map =
mmap(0, creq.size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, mreq.offset);
if (map == MAP_FAILED) {
fprintf(stderr, "cannot mmap dumb buffer (%d): %m\n", errno);
return -errno;
}
/* clear the framebuffer to 0 */
memset(map, 0, creq.size);
for (int i = 0; i < 8; i++) {
printf(" 0x%x ", map[i]);
}
printf("\n");
dreq.handle = creq.handle;
drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dreq);
printf("dumb destroyed\n");
return 0;
}
int main(int argc, char** argv) {
int fd = open("/dev/dri/card0", O_RDWR);
if (fd > 0) {
printf("drmOpen Succeed\n");
} else {
printf("drmOpen failed, fd=0x%x\n", fd);
return -1;
}
test_dumb(fd);
close(fd);
return 0;
}
然后使用如下命令编译:
gcc dumb.c -I/usr/include/drm/ -ldrm -o dumb
代码里,先打开了/dev/dri/card0设备,然后create了一个dumb buffer,创建完了的dumb buffer,通过handle返回。之后我们就可以通过这个handle来唯一区分这个buffer了。再通过drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &mreq),将buffer请求map,之后调用mmap进行真正的map,这样就可以拿到map出来的虚拟地址。然后可以对这个虚拟地址,进行读和写操作。最后通过这个handle,将整个dumb buffer 销毁掉。
可以看出,dumb buffer,主要是通过drmIoctl函数,第2个参数和第3个参数传递下面表格的参数,进行使用的。
ioctl | 结构体 |
---|---|
DRM_IOCTL_MODE_CREATE_DUMB | struct drm_mode_create_dumb |
DRM_IOCTL_MODE_MAP_DUMB | struct drm_mode_map_dumb |
DRM_IOCTL_MODE_DESTROY_DUMB | struct drm_mode_destroy_dumb |
而在使用的过程中,通过同一个handle来表示同一个dumb buffer。