libdrm全解析三十二 —— 源码全解析(29)

接前一篇文章:libdrm全解析三十一 —— 源码全解析(28)

本文参考以下博文:

DRM 驱动程序开发(VKMS)

特此致谢!

本文开始对于DRM_IOCTL_MODE_ADDFB对应的Userspace API drmModeAddFB()进行解析。再次贴出该函数源码,在xf86drmMode.c中,如下:

drm_public int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth,
                            uint8_t bpp, uint32_t pitch, uint32_t bo_handle,
                            uint32_t *buf_id)
{
	struct drm_mode_fb_cmd f;
	int ret;
 
	memclear(f);
	f.width  = width;
	f.height = height;
	f.pitch  = pitch;
	f.bpp    = bpp;
	f.depth  = depth;
	f.handle = bo_handle;
 
	if ((ret = DRM_IOCTL(fd, DRM_IOCTL_MODE_ADDFB, &f)))
		return ret;
 
	*buf_id = f.fb_id;
	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函数中,在上一步通过drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &create)根据之前调用_drmModeGetConnector函数获得的宽高信息创建显存后,调用drmModeAddFB(fd, create.width, create.height, 24, 32, create.pitch,create.handle, &fb_id)向DRM驱动注册一个framebuffer object。

drmModeAddFB函数本身很简单,就是根据函数的入参设置struct drm_mode_fb_cmd f。设置好之后调用DRM_IOCTL(fd, DRM_IOCTL_MODE_ADDFB, &f),这就是核心功能:向DRM驱动注册一个framebuffer对象(object)。成功后将framebuffer对象的id返回。

drmModeAddFB函数的核心结构体struct drm_mode_fb_cmd在include/libdrm/drm_mode.h中定义,代码如下:

struct drm_mode_fb_cmd {
	__u32 fb_id;
	__u32 width;
	__u32 height;
	__u32 pitch;
	__u32 bpp;
	__u32 depth;
	/* driver specific handle */
	__u32 handle;
};

至此,drmModeAddFB()这一步就讲解完了。

猜你喜欢

转载自blog.csdn.net/phmatthaus/article/details/132576544