前回の記事:DRMの完全解析 - ADD_FB (1)の続きです。
この記事は次のブログ投稿を参照しています。
ありがとう!
前の章では、Linux カーネルの libdrm と DRM の間のインターフェイスに焦点を当てました。
DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb_ioctl, 0),
関連するマクロを拡張しました。この記事では、drm_mode_addfb_ioctl 関数の詳細な説明から始めます。drm_mode_addfb_ioctl 関数は drivers/gpu/drm/drm_framebuffer.c にあります。コードは次のとおりです。
int drm_mode_addfb_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv)
{
return drm_mode_addfb(dev, data, file_priv);
}
drm_mode_addfb_ioctl 関数は単純なカプセル化にすぎず、実際の作業は drm_mode_addfb 関数に任せられます。すぐ上にあり、コードは次のとおりです。
/**
* 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;
}
この関数を説明する前に、ユーザー空間の一般的なプロセスでこのステップ (ioctl システム コール) を呼び出すコンテキストを見てみましょう。
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);
libdrm 完全分析シリーズの記事と DRM 完全分析 - CREATE_DUMB シリーズの記事で述べたように、ユーザー空間では
drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &create)
最後に、カーネル内で異なるグラフィックスドライバーに対応する関数内でダムバッファオブジェクトが作成され(実際には struct drm_gem_object *gobj が割り当てられます)、割り当てられた struct drm_gem_object *gobj にバインドされたハンドルが返されます。
drm_gem_object を作成した後、それを drm_framebuffer にバインドする必要があります。これは、fb が最終的な描画に使用されるためです。したがって、drmModeAddFB インターフェイスを使用して drm_framebuffer を作成し、それを以前に作成した struct drm_gem_object *gobj にバインドします。
ユーザー モードとカーネル モードでの DRM_IOCTL_MODE_ADDFB マクロの上下の呼び出しプロセスは、次の図に示すようになります。
drm_mode_addfb 関数の詳細な分析は次の記事に残しておきます。