Continuing from the previous article: Full analysis of DRM - ADD_FB (1)
This article refers to the following blog posts:
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.