DRM full analysis - ADD_FB (2)

Continuing from the previous article: Full analysis of DRM - ADD_FB (1)

This article refers to the following blog posts:

DRM driver (4) ADD_FB

Thanks!

The previous chapter focused on the interface between libdrm and DRM in the Linux kernel:

DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb_ioctl, 0),

Expanded related macros. This article begins with a detailed explanation of the drm_mode_addfb_ioctl function. The drm_mode_addfb_ioctl function is in drivers/gpu/drm/drm_framebuffer.c. The code is as follows:

int drm_mode_addfb_ioctl(struct drm_device *dev,
			 void *data, struct drm_file *file_priv)
{
	return drm_mode_addfb(dev, data, file_priv);
}

The drm_mode_addfb_ioctl function is just a simple encapsulation, and the actual work is left to the drm_mode_addfb function. It's right above, and the code is as follows:

/**
 * drm_mode_addfb - add an FB to the graphics configuration
 * @dev: drm device for the ioctl
 * @or: pointer to request structure
 * @file_priv: drm file
 *
 * Add a new FB to the specified CRTC, given a user request. This is the
 * original addfb ioctl which only supported RGB formats.
 *
 * Called by the user via ioctl, or by an in-kernel client.
 *
 * Returns:
 * Zero on success, negative errno on failure.
 */
int drm_mode_addfb(struct drm_device *dev, struct drm_mode_fb_cmd *or,
		   struct drm_file *file_priv)
{
	struct drm_mode_fb_cmd2 r = {};
	int ret;

	if (!drm_core_check_feature(dev, DRIVER_MODESET))
		return -EOPNOTSUPP;

	r.pixel_format = drm_driver_legacy_fb_format(dev, or->bpp, or->depth);
	if (r.pixel_format == DRM_FORMAT_INVALID) {
		drm_dbg_kms(dev, "bad {bpp:%d, depth:%d}\n", or->bpp, or->depth);
		return -EINVAL;
	}

	/* convert to new format and call new ioctl */
	r.fb_id = or->fb_id;
	r.width = or->width;
	r.height = or->height;
	r.pitches[0] = or->pitch;
	r.handles[0] = or->handle;

	ret = drm_mode_addfb2(dev, &r, file_priv);
	if (ret)
		return ret;

	or->fb_id = r.fb_id;

	return 0;
}

Before explaining this function, let's take a look at the context of calling this step (ioctl system call) in the general process of user space:

    struct drm_mode_create_dumb create = {};
	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); 

As mentioned in the libdrm full analysis series of articles and the DRM full analysis - CREATE_DUMB series of articles, in user space

drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &create)

Finally, a dumb buffer object is created in the kernel in the corresponding functions of different graphics drivers (actually struct drm_gem_object *gobj is allocated), and the handle bound to the allocated struct drm_gem_object *gobj is returned.

After the drm_gem_object is created, it needs to be bound to a drm_framebuffer, because fb is used for final painting. Therefore, use the drmModeAddFB interface to create drm_framebuffer and bind it to the previously created struct drm_gem_object *gobj.

The up and down calling process around the DRM_IOCTL_MODE_ADDFB macro in user mode and kernel mode is as shown in the figure below:

A detailed analysis of the drm_mode_addfb function will be left in the next article.

Guess you like

Origin blog.csdn.net/phmatthaus/article/details/132646813