接前一篇文章:libdrm全解析二十九 —— 源码全解析(26)
本文参考以下博文:
特此致谢!
本文开始对drmIoctl(DRM_IOCTL_MODE_CREATE_DUMB)以及其封装函数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;
}
实际使用中,可以使用drmModeCreateDumbBuffer函数,但更一般地是直接使用drmIoctl(DRM_IOCTL_MODE_CREATE_DUMB)函数。
实际调用的代码示例片段为:
struct drm_mode_create_dumb create = {};
/* create a dumb-buffer, the pixel format is XRGB888 */
create.width = bo->width;
create.height = bo->height;
create.bpp = 32;
drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &create);
另一实力片段:
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函数传入的参数就是上一步通过_drmModeGetConnector函数得到的connector的相关信息。为了便于理解,再次贴出struct _drmModeConnector的定义,在xf86drmMode.h中,如下:
扫描二维码关注公众号,回复:
16396620 查看本文章
typedef struct _drmModeConnector {
uint32_t connector_id;
uint32_t encoder_id; /**< Encoder currently connected to */
uint32_t connector_type;
uint32_t connector_type_id;
drmModeConnection connection;
uint32_t mmWidth, mmHeight; /**< HxW in millimeters */
drmModeSubPixel subpixel;
int count_modes;
drmModeModeInfoPtr modes;
int count_props;
uint32_t *props; /**< List of property ids */
uint64_t *prop_values; /**< List of property values */
int count_encoders;
uint32_t *encoders; /**< List of encoder ids */
} drmModeConnector, *drmModeConnectorPtr;
drmModeModeInfoPtr的定义也在xf86drmMode.h中,代码如下:
typedef struct _drmModeModeInfo {
uint32_t clock;
uint16_t hdisplay, hsync_start, hsync_end, htotal, hskew;
uint16_t vdisplay, vsync_start, vsync_end, vtotal, vscan;
uint32_t vrefresh;
uint32_t flags;
uint32_t type;
char name[DRM_DISPLAY_MODE_LEN];
} drmModeModeInfo, *drmModeModeInfoPtr;
来看drmIoctl(DRM_IOCTL_MODE_CREATE_DUMB)以及其封装函数drmModeCreateDumbBuffer()中的关键结构体struct drm_mode_create_dumb,其定义在include/drm/drm_mode.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;
};
实际上drmIoctl(DRM_IOCTL_MODE_CREATE_DUMB)这一步不难理解,就是根据之前获得的相关信息,然后以获取的宽度和高度信息,通过ioctl系统调用创建一个dumb buffer对象。
至此,drmIoctl(DRM_IOCTL_MODE_CREATE_DUMB)这一步就讲解完了。