本文主要是介绍uvc_app里面自定义的drm,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
直接上代码:
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <unistd.h>#include <libdrm/drm.h>
#include <libdrm/drm_mode.h>
#include "drm.h"
#include "uvc_log.h"#define DRM_DEVICE "/dev/dri/card0"int drm_open(void) //打开DRM设备文件
{int fd;fd = open(DRM_DEVICE, O_RDWR);if (fd < 0){LOG_ERROR("open %s failed!\n", DRM_DEVICE);return -1;}return fd;
}void drm_close(int fd)
{if (fd >= 0)close(fd);
}static int drm_ioctl(int fd, int req, void *arg) //用于封装ioctl系统调用,用于向DRM设备发送控制命令
{int ret;do{ret = ioctl(fd, req, arg);}while (ret == -1 && (errno == EINTR || errno == EAGAIN));return ret;
}int drm_alloc(int fd, size_t len, size_t align, unsigned int *handle, unsigned int flags) //分配显存
{int ret;struct drm_mode_create_dumb dmcb;memset(&dmcb, 0, sizeof(struct drm_mode_create_dumb));dmcb.bpp = 8;dmcb.width = (len + align - 1) & (~(align - 1));dmcb.height = 1;dmcb.flags = flags;if (handle == NULL)return -EINVAL;ret = drm_ioctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &dmcb);if (ret < 0)return ret;*handle = dmcb.handle;return ret;
}int drm_free(int fd, unsigned int handle) //释放通过drm_alloc函数分配的显存
{struct drm_mode_destroy_dumb data ={.handle = handle,};return drm_ioctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &data);
}void *drm_map_buffer(int fd, unsigned int handle, size_t len) //映射显存到用户空间
{struct drm_mode_map_dumb dmmd;void *buf = NULL;int ret;memset(&dmmd, 0, sizeof(dmmd));dmmd.handle = handle;ret = drm_ioctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &dmmd);if (ret){LOG_ERROR("map_dumb failed: %s\n", strerror(ret));return NULL;}buf = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, dmmd.offset);if (buf == MAP_FAILED){LOG_ERROR("mmap failed: %s\n", strerror(errno));return NULL;}return buf;
}void drm_unmap_buffer(void *buf, size_t len) //取消之前由drm_map_buffer函数映射到用户空间的缓冲区
{if (buf)munmap(buf, len);
}int drm_handle_to_fd(int fd, unsigned int handle, int *map_fd, unsigned int flags) //将给定的DRM句柄(handle)转换为对应的文件描述符(file descriptor)
{int ret;struct drm_prime_handle dph;memset(&dph, 0, sizeof(struct drm_prime_handle));dph.handle = handle;dph.fd = -1;dph.flags = flags;if (map_fd == NULL)return -EINVAL;ret = drm_ioctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &dph);if (ret < 0)return ret;*map_fd = dph.fd;if (*map_fd < 0){LOG_ERROR("map ioctl returned negative fd\n");return -EINVAL;}return ret;
}int drm_get_info_from_name(int fd,unsigned int name,unsigned int *handle,int *size) //通过名称获取DRM信息
{int ret = 0;struct drm_gem_open req;req.name = name;ret = drm_ioctl(fd, DRM_IOCTL_GEM_OPEN, &req);if (ret < 0){return ret;}*handle = req.handle;*size = (int)req.size;return ret;
}
这段代码是一个使用DRM(Direct Rendering Manager)库的示例代码,用于在Linux系统中进行图形渲染和显示控制。DRM是一个内核模块,提供了用户空间程序与硬件之间的接口,用于管理显示设备和图形加速硬件。
该代码中包含了一些函数,如drm_open用于打开DRM设备文件,drm_alloc用于分配显存,drm_map_buffer用于映射显存到用户空间等。
drm_ioctl
在这段代码中,drm_ioctl是一个自定义的函数,用于封装ioctl系统调用,用于向DRM设备发送控制命令。在Linux中,ioctl系统调用通常用于设备的控制和配置。
具体来说,该函数的作用是向打开的DRM设备文件描述符fd发送req所指定的控制命令,arg是控制命令的参数,函数会一直尝试ioctl直到成功为止。
需要注意的是,ioctl系统调用在Linux中是一个相对底层的操作,使用时需要对设备的控制命令有一定的了解,并且需要小心处理各种错误情况。
在这段代码中,drm_ioctl函数封装了ioctl调用,处理了一些常见的错误情况,并提供了更友好的接口给上层调用,使得代码更易于使用和维护。
drm_alloc
这段代码是一个用于在DRM设备上分配显存的函数实现。
首先,它接受了五个参数:文件描述符fd
、要分配的长度len
、对齐方式align
、用于接收句柄的指针handle
以及标志flags
。
在函数内部,它先声明了一个struct drm_mode_create_dumb
结构体dmcb
,并将其清零初始化。
然后,它设置了dmcb
结构体的一些字段,其中bpp
表示每个像素占用的位数,width
表示分配的空间大小(经过对齐处理),height
为1,flags
为传入的标志。
接着,它检查了handle
的合法性,如果为NULL
,则返回-EINVAL
,表示参数错误。
接下来,它调用drm_ioctl
函数,向DRM设备发送DRM_IOCTL_MODE_CREATE_DUMB
命令,并传入dmcb
结构体。如果返回值小于0,表示出现错误,直接将错误码返回。
最后,如果一切顺利,它将dmcb.handle
的值赋给传入的*handle
,并返回之前drm_ioctl
的返回值。
总的来说,这个函数的作用是向DRM设备请求分配一块显存,返回分配成功与否的状态,并将分配的句柄通过参数返回供使用。
drm_free
在这段代码中,drm_free函数用于释放通过drm_alloc函数分配的显存。它接受一个文件描述符fd和一个handle参数,其中fd是已经打开的DRM设备文件描述符,handle是要释放的显存的句柄。
具体来说,drm_free函数会构造一个drm_mode_destroy_dumb结构体,并将handle赋值给结构体的handle字段。然后调用drm_ioctl函数,向fd发送DRM_IOCTL_MODE_DESTROY_DUMB命令,并将构造的结构体传递给ioctl系统调用。
该命令的作用是销毁通过DRM_IOCTL_MODE_CREATE_DUMB命令创建的显存资源,释放占用的系统资源。
需要注意的是,在调用drm_free函数之前,必须先通过drm_alloc函数成功地分配显存,并且确保handle参数的正确性。
drm_map_buffer
这段代码是一个用于将DRM设备的显存映射到用户空间的函数实现。
首先,它接受了三个参数:文件描述符fd
、分配的显存句柄handle
以及显存长度len
。
在函数内部,它声明了一个struct drm_mode_map_dumb
结构体dmmd
,并将其清零初始化。然后,它将传入的handle
赋值给dmmd.handle
字段。
接着,它调用drm_ioctl
函数,向DRM设备发送DRM_IOCTL_MODE_MAP_DUMB
命令,并传入dmmd
结构体作为参数。如果返回值不为0,说明映射失败,直接返回NULL
。
如果映射成功,它将使用mmap
函数将显存映射到用户空间,并将映射的地址赋值给buf
。
最后,如果一切顺利,它将返回buf
指针,也就是映射到用户空间的显存地址。
总的来说,这个函数的作用就是将DRM设备的显存映射到用户空间,以便用户可以进行读写操作。
drm_handle_to_fd
这段代码是一个用于将给定的DRM句柄(handle)转换为对应的文件描述符(file descriptor)的函数实现。
这个函数接受了四个参数:文件描述符fd
、要转换的句柄handle
、用于接收文件描述符的指针map_fd
以及标志flags
。
在函数内部,它首先声明了一个struct drm_prime_handle
结构体dph
,并将其清零初始化。然后,设置了dph
结构体的handle
和flags
字段,同时将dph.fd
初始化为-1。
接着,它检查了map_fd
的合法性,如果为NULL
,则返回-EINVAL
,表示参数错误。
然后,它调用drm_ioctl
函数,向DRM设备发送DRM_IOCTL_PRIME_HANDLE_TO_FD
命令,并传入dph
结构体。如果返回值小于0,表示出现错误,直接将错误码返回。
如果一切顺利,它将dph.fd
的值赋给传入的*map_fd
,并进行进一步检查,如果*map_fd
小于0,表示出现错误,返回-EINVAL
。
最后,它返回了之前drm_ioctl
的返回值。
总的来说,这个函数的作用是将给定的DRM句柄转换为对应的文件描述符,并通过参数返回供使用。
这篇关于uvc_app里面自定义的drm的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!