libdrm全解析二十九 —— 源码全解析(26)

接前一篇文章: libdrm全解析二十八 —— 源码全解析(25)

本文参考以下博文:

DRM 驱动程序开发(VKMS)

特此致谢!

前一篇文章讲解完了_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函数的详细解析,将在下篇文章中进行。

猜你喜欢

转载自blog.csdn.net/phmatthaus/article/details/132563206