接前一篇文章:KWin、libdrm、DRM从上到下全过程 —— drmModeAddFBxxx(1)
上回书说到drmModeAddFB、drmModeAddFB2和drmModeAddFB2WithModifiers函数最终“三分归一统”,在内核层统一调用到drm_mode_addfb2函数。
这里我们先不急于往下分析drm_mode_addfb2函数,而是再来回顾一下之前的逐步合并统一的过程,以加深理解。如下图所示:
重点关注函数两次合并过程中同级函数的差异:
第1次合并
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)
- {
- ……
- }
- 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结构的转换,这样两者才能最终统一起来。
欲知后事如何,且看下回分解。