接前一篇文章: libdrm全解析二十八 —— 源码全解析(25)
本文参考以下博文:
特此致谢!
前一篇文章讲解完了_drmModeGetConnector函数,本篇文章继续讲解DRM一般流程的下一步。为了便于理解,再次贴出一般流程示例:
int main(int argc, char **argv)
{
/* open the drm device */
open("/dev/dri/card0");
/* get crtc/encoder/connector id */
drmModeGetResources(...);
/* get connector for display mode */
drmModeGetConnector(...);
/* create a dumb-buffer */
drmIoctl(DRM_IOCTL_MODE_CREATE_DUMB);
/* bind the dumb-buffer to an FB object */
drmModeAddFB(...);
/* map the dumb buffer for userspace drawing */
drmIoctl(DRM_IOCTL_MODE_MAP_DUMB);
mmap(...);
/* start display */
drmModeSetCrtc(crtc_id, fb_id, connector_id, mode);
}
下一步是drmIoctl(DRM_IOCTL_MODE_CREATE_DUMB)。
78. DRM_IOCTL_MODE_CREATE_DUMB
第78个宏是DRM_IOCTL_MODE_CREATE_DUMB,相应代码如下:
#define DRM_IOCTL_MODE_CREATE_DUMB DRM_IOWR(0xB2, struct drm_mode_create_dumb)
结合之前文章中的_IOWR(type,nr,size)的最终定义,得到如下代码:
#define DRM_IOCTL_MODE_CREATE_DUMB ( ((3) << 30) | (('d') << 8) | ((0xB2) << 0) | ((sizeof(struct drm_mode_create_dumb)) << 16) )
struct drm_mode_create_dumb在同文件(include/drm/drm.h)中定义,代码如下:
/* create a dumb scanout buffer */
struct drm_mode_create_dumb {
__u32 height;
__u32 width;
__u32 bpp;
__u32 flags;
/* handle, pitch, size will be returned */
__u32 handle;
__u32 pitch;
__u64 size;
};
DRM_IOCTL_MODE_CREATE_DUMB对应的Userspace API为:drmModeCreateDumbBuffer()。该函数在xf86drmMode.c中,代码如下:
drm_public int
drmModeCreateDumbBuffer(int fd, uint32_t width, uint32_t height, uint32_t bpp,
uint32_t flags, uint32_t *handle, uint32_t *pitch,
uint64_t *size)
{
int ret;
struct drm_mode_create_dumb create = {
.width = width,
.height = height,
.bpp = bpp,
.flags = flags,
};
ret = DRM_IOCTL(fd, DRM_IOCTL_MODE_CREATE_DUMB, &create);
if (ret != 0)
return ret;
*handle = create.handle;
*pitch = create.pitch;
*size = create.size;
return 0;
}
DRM_IOCTL的定义在同文件中,代码如下:
static inline int DRM_IOCTL(int fd, unsigned long cmd, void *arg)
{
int ret = drmIoctl(fd, cmd, arg);
return ret < 0 ? -errno : ret;
}
DRM_IOCTL函数实际上就是drmIoctl函数的一层封装。
drmModeCreateDumbBuffer函数的作用是创建一个dumb buffer对象。
这里要补充一下DUMB Buffer的相关知识。
DUMB Buffer
如果我们去百度翻译上查询“dumb”一词的含义,得到的解释有2种:1.“哑的” 2. “傻的”
哑的 buffer ?什么鬼!而如果我们在 Ubuntu 下运行 man drm-memory 命令,则会得到如下关于 Dumb-Buffer 的解释:These buffers can be memory mapped via mmap(2) so you can render into them on the CPU. However, GPU access to these buffers is often not possible.
大意就是该buffer通常不能用于GPU硬件加速,只能给CPU使用。但是不能用于硬件加速的buffer为什么要叫 dumb buffer 呢?为何不直接叫 simple buffer 呢?“dumb”一词在这里到底是什么含义呢?其实这还得从上世纪80年代的VGA显卡说起。
那时的显卡由一块很小的显存(通常为640x480)加一块数模转换电路(DAC)组成,说白了就是一块Framebuffer + Display Controller。显卡的功能极其简单,只负责将显存中的图像数据转换成RGB信号发送出去即可,而所有的绘图操作则都交给CPU来完成。行业里将这种显卡称为VGA Card,它的显存则被称为“Dumb Frame Buffer”。而到了后期,随着显卡技术的不断发展,许多原来由CPU干的活,渐渐的都被显卡取代了。从最初支持某些特定绘图指令(如画点、画线)的显卡,到后来支持视频解码的Video Card,再到现代支持复杂3D渲染指令(如OpenGL)的GPU显卡,CPU绘图的繁重任务彻底得到了解放。与VGA Card相比较,行业里将后来显卡的显存称为“Smart Frame Buffer”。首先从这两种称谓上我们就可以看出,dumb是smart的反义词,因此dumb在这里的解释应该是“傻的”或“傻瓜式的”,而不是“哑的”。
对于drmModeCreateDumbBuffer函数的详细解析,将在下篇文章中进行。