libdrm全解析三十五 —— 源码全解析(32)

接前一篇文章:libdrm全解析三十四 ------ 源码全解析(31)

本文参考以下博文:

DRM 驱动程序开发(VKMS)

特此致谢!

前一篇文章讲解完了drmIoctl(DRM_IOCTL_MODE_MAP_DUMB)以及其封装函数drmModeMapDumbBuffer(),本篇文章继续讲解DRM一般流程的下一步。为了便于理解,再次贴出一般流程示例:

cpp 复制代码
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);
}

下一步是mmap。实际使用中调用的代码示例片段如下:

cpp 复制代码
static void create_fb(int fd,uint32_t width, uint32_t height, uint32_t color ,struct framebuffer *buf)
{
	struct drm_mode_create_dumb create = {};
 	struct drm_mode_map_dumb map = {};
	uint32_t i;
	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); 
	
	map.handle = create.handle;
	drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &map);	//显存绑定fd,并根据handle返回offset
 
	//通过offset找到对应的显存(framebuffer)并映射到用户空间
	uint32_t *vaddr = mmap(0, create.size, PROT_READ | PROT_WRITE,MAP_SHARED, fd, map.offset);	
 
	for (i = 0; i < (create.size / 4); i++)
		vaddr[i] = color;
 
	buf->vaddr=vaddr;
	buf->handle=create.handle;
	buf->size=create.size;
	buf->fb_id=fb_id;
 
	return;
}
 
create_fb(fd,connector->modes[0].hdisplay,connector->modes[0].vdisplay, 0xff0000, &buf[0]);	

create_fb函数中,在上一步通过drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &map)将dumb buffer与fd绑定,并根据handle返回offset后,在此调用了mmap函数,将通过offset得到的对应dumb buffer映射到用户空间。

在映射完成后,写入用户空间内存vaddr的访问(读写),实际上就是对于显存的访问了。

struct framebuffer是示例代码中自定义的结构,如下:

cpp 复制代码
struct framebuffer{
	uint32_t size;
	uint32_t handle;	
	uint32_t fb_id;
	uint32_t *vaddr;	
};

至此,mmap()这一步就讲解完了。

相关推荐
一梦浮华44 分钟前
自学嵌入式 day30 IPC:进程间通信
linux·运维·服务器
CH_Qing1 小时前
【udev】关于/dev 设备节点的生成 &udev
linux·前端·网络
电脑能手1 小时前
遇到该问题:kex_exchange_identification: read: Connection reset`的解决办法
linux·ubuntu·ssh
snoopyfly~1 小时前
Ubuntu 24.04 安装配置 Redis 7.0 开机自启
linux·redis·ubuntu
精英的英1 小时前
在Ubuntu 24.04主机上创建Ubuntu 14.04编译环境的完整指南
linux·运维·ubuntu
求索小沈1 小时前
ubuntu22.04安装anaconda
linux·运维·服务器
小张不嚣张꒰ঌ(˚ᆺ˚)໒꒱2 小时前
Centos7在yum当中遇到Could not resolve host: mirrorlist.centos.org解决方案
linux·运维·服务器·centos
Sally璐璐2 小时前
CentOS企业级文件服务器终极部署指南
linux·服务器·centos
岁月玲珑2 小时前
【如何判断Linux系统是Ubuntu还是CentOS】
linux·ubuntu·centos
梅孔立2 小时前
yum update 报错 Cannot find a valid baseurl for repo: centos-sclo-rh/x86_64 等解决办法
linux·python·centos