接前一篇文章:libdrm全解析三十三 —— 源码全解析(30)
本文参考以下博文:
特此致谢!
本文开始对于DRM_IOCTL_MODE_MAP_DUMB对应的Userspace API drmModeMapDumbBuffer()进行解析。再次贴出该函数源码,在xf86drmMode.c中,如下:
drm_public int
drmModeMapDumbBuffer(int fd, uint32_t handle, uint64_t *offset)
{
int ret;
struct drm_mode_map_dumb map = {
.handle = handle,
};
ret = DRM_IOCTL(fd, DRM_IOCTL_MODE_MAP_DUMB, &map);
if (ret != 0)
return ret;
*offset = map.offset;
return 0;
}
实际使用中调用的代码示例片段如下:
static void create_fb(int fd,uint32_t width, uint32_t height, uint32_t color ,struct framebuffer *buf)
{
struct drm_mode_create_dumb create = {};
struct drm_mode_map_dumb map = {};
uint32_t i;
uint32_t fb_id;
create.width = width;
create.height = height;
create.bpp = 32;
drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &create); //创建显存,返回一个handle
drmModeAddFB(fd, create.width, create.height, 24, 32, create.pitch,create.handle, &fb_id);
map.handle = create.handle;
drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &map); //显存绑定fd,并根据handle返回offset
//通过offset找到对应的显存(framebuffer)并映射到用户空间
uint32_t *vaddr = mmap(0, create.size, PROT_READ | PROT_WRITE,MAP_SHARED, fd, map.offset);
for (i = 0; i < (create.size / 4); i++)
vaddr[i] = color;
buf->vaddr=vaddr;
buf->handle=create.handle;
buf->size=create.size;
buf->fb_id=fb_id;
return;
}
create_fb(fd,connector->modes[0].hdisplay,connector->modes[0].vdisplay, 0xff0000, &buf[0]);
create_fb函数中,在上一步通过drmModeAddFB(fd, create.width, create.height, 24, 32, create.pitch,create.handle, &fb_id)向DRM驱动注册一个framebuffer object后,直接调用drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &map)将将dumb buffer与fd绑定,并根据handle返回offset。注意,这里并没有使用drmModeMapDumbBuffer函数,而是直接调用了drmIoctl函数,不过意思是一样的。
drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &map)及其对应drmModeMapDumbBuffer函数的核心结构体struct drm_mode_map_dumb在include/libdrm/drm_mode.h中定义,代码如下:
/* 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;
};
至此,drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &map)这一步就讲解完了。