DRM全解析 —— MAP_DUMB(2)

接前一篇文章:DRM全解析 —— MAP_DUMB(1)

上一回围绕libdrm与DRM在Linux内核中的接口:

DRM_IOCTL_DEF(DRM_IOCTL_MODE_MAP_DUMB, drm_mode_mmap_dumb_ioctl, 0),

进行了相关宏的展开。本文开始对于drm_mode_mmap_dumb_ioctl函数进行详解。drm_mode_mmap_dumb_ioctl函数在drivers/gpu/drm/drm_framebuffer.c中,代码如下:

/**
 * drm_mode_mmap_dumb_ioctl - create an mmap offset for a dumb backing storage buffer
 * @dev: DRM device
 * @data: ioctl data
 * @file_priv: DRM file info
 *
 * Allocate an offset in the drm device node's address space to be able to
 * memory map a dumb buffer.
 *
 * Called by the user via ioctl.
 *
 * Returns:
 * Zero on success, negative errno on failure.
 */
int drm_mode_mmap_dumb_ioctl(struct drm_device *dev,
			     void *data, struct drm_file *file_priv)
{
	struct drm_mode_map_dumb *args = data;

	if (!dev->driver->dumb_create)
		return -ENOSYS;

	if (dev->driver->dumb_map_offset)
		return dev->driver->dumb_map_offset(file_priv, dev,
						    args->handle,
						    &args->offset);
	else
		return drm_gem_dumb_map_offset(file_priv, dev, args->handle,
					       &args->offset);
}

drm_mode_mmap_dumb_ioctl可没像drm_mode_addfb_ioctl和drm_mode_create_dumb_ioctl函数那样只是一层简单封装,实际的工作交给了drm_mode_mmap_dumb函数。人家压根儿就没用也没有drm_mode_mmap_dumb函数,而是自己完成了实际的工作。

在讲解此函数之前,先来看一下用户空间一般流程中调用此步骤(ioctl系统调用)的上下文:

    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);	

在libdrm全解析系列文章以及DRM全解析 —— CREATE_DUMB系列文章中讲过,在用户空间中通过

drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &create)

最终在内核中在不同的显卡驱动相对应的函数中创建了一个dumb buffer对象(实际上是分配了struct drm_gem_object *gobj),返回的是与分配的struct drm_gem_object *gobj绑定的handle。

而在libdrm全解析系列文章以及DRM全解析 —— ADD_FB系列文章中讲过,drm_gem_object创建之后需要与一块drm_framebuffer进行绑定使用,因为最终刷图使用的是fb。因此,在用户空间中使用下面接口

drmModeAddFB(fd, create.width, create.height, 24, 32, create.pitch,create.handle, &fb_id)

创建drm_framebuffer并与之前创建的struct drm_gem_object *gobj进行绑定。

围绕DRM_IOCTL_MODE_MAP_DUMB宏的用户态和内核态上下调用流程,如下图所示:

猜你喜欢

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