接前一篇文章:KWin、libdrm、DRM从上到下全过程 —— drmModeAddFBxxx(1)
上回书说到drmModeAddFB、drmModeAddFB2和drmModeAddFB2WithModifiers函数最终“三分归一统”,在内核层统一调用到drm_mode_addfb2函数。
这里我们先不急于往下分析drm_mode_addfb2函数,而是再来回顾一下之前的逐步合并统一的过程,以加深理解。如下图所示:
重点关注函数两次合并过程中同级函数的差异:
第1次合并
- DRM <——> libdrm
drmModeAddFB2(buffer->gpu()->fd(), size.width(), size.height(), buffer->format(), handles.data(), strides.data(), offsets.data(), &framebufferId, 0);
drmModeAddFB2WithModifiers(buffer->gpu()->fd(), size.width(), size.height(), buffer->format(), handles.data(), strides.data(), offsets.data(), modifier, &framebufferId, DRM_MODE_FB_MODIFIERS);
drm_public int drmModeAddFB2(int fd, uint32_t width, uint32_t height,
uint32_t pixel_format, const uint32_t bo_handles[4],
const uint32_t pitches[4], const uint32_t offsets[4],
uint32_t *buf_id, uint32_t flags)
{
return drmModeAddFB2WithModifiers(fd, width, height,
pixel_format, bo_handles,
pitches, offsets, NULL,
buf_id, flags);
}
drm_public int drmModeAddFB2WithModifiers(int fd, uint32_t width,
uint32_t height, uint32_t pixel_format, const uint32_t bo_handles[4],
const uint32_t pitches[4], const uint32_t offsets[4],
const uint64_t modifier[4], uint32_t *buf_id, uint32_t flags)
{
……
}
- libdrm <——> DRM
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;
}
drm_public int drmModeAddFB2WithModifiers(int fd, uint32_t width,
uint32_t height, uint32_t pixel_format, const uint32_t bo_handles[4],
const uint32_t pitches[4], const uint32_t offsets[4],
const uint64_t modifier[4], uint32_t *buf_id, uint32_t flags)
{
struct drm_mode_fb_cmd2 f;
int ret;
memclear(f);
f.width = width;
f.height = height;
f.pixel_format = pixel_format;
f.flags = flags;
memcpy(f.handles, bo_handles, 4 * sizeof(bo_handles[0]));
memcpy(f.pitches, pitches, 4 * sizeof(pitches[0]));
memcpy(f.offsets, offsets, 4 * sizeof(offsets[0]));
if (modifier)
memcpy(f.modifier, modifier, 4 * sizeof(modifier[0]));
if ((ret = DRM_IOCTL(fd, DRM_IOCTL_MODE_ADDFB2, &f)))
return ret;
*buf_id = f.fb_id;
return 0;
}
第2次合并
int drm_mode_addfb_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv)
{
return drm_mode_addfb(dev, data, file_priv);
}
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;
……
/* 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;
}
int drm_mode_addfb2_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv)
{
#ifdef __BIG_ENDIAN
……
#endif
return drm_mode_addfb2(dev, data, file_priv);
}
由代码可以看到,drm_mode_addfb函数中存在由drm_mode_fb_cmd结构向drm_mode_fb_cmd2结构的转换,这样两者才能最终统一起来。
欲知后事如何,且看下回分解。