下面是一个最简单的case,使用的是dumb buffer显示
1.为什么最终是用fb_id::因为fb_id是对应drm_framebuffer管理,也就是drm机制只认fb_id
目前DRM主要推荐使用的是 Atomic(原子的) 接口;Atomic操作必须依赖的基本元素,Property(属性)。
所谓Property,其实就是把legacy接口传入的参数单独抽出来,做成一个个独立的全局属性。通过设置这些属性参数,即可完成对显示参数的设置。
Property的结构简单概括主要由3部分组成:name、id 和 value。
其中id为该property在DRM框架中全局唯一的标识符。
操作property,通过name 来获取property,通过id 来操作property,通过value 来修改property的值
Property的类型分为如下几种:
• enum
• bitmask
• range
• signed range
• object
• blob
From <https://blog.csdn.net/hexiaolong2009/article/details/87211230>
drm_property的定义:
https://elixir.bootlin.com/linux/latest/source/include/drm/drm_property.h#L73
对应的详细说明:
https://www.kernel.org/doc/html/latest/gpu/drm-kms.html#c.drm_property
133 typedef struct _drmModeProperty {
134 uint32_t prop_id;
135 uint32_t flags;
136 char name[DRM_PROP_NAME_LEN];
137 int count_values;
138 uint64_t *values; /* store the blob lengths */
139 int count_enums;
140 struct drm_mode_property_enum *enums;
141 int count_blobs;
142 uint32_t *blob_ids; /* store the blob IDs */
143 } drmModePropertyRes, *drmModePropertyPtr;
2.为什么handle可以获得fb_id::是因为handle可以找到对应gem object,而drm为gem object创建drm_framebuffer,随后把这个framebuffer 的fb_id给你
3.需要讲清楚modeset_create_fb里面的过程
#include "xf86drm.h"
#include "xf86drmMode.h"
#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/mman.h>
struct buffer_object {
uint32_t width;
uint32_t height;
uint32_t pitch;
uint32_t handle;
uint32_t size;
uint8_t *vaddr;
uint32_t fb_id;
};
struct buffer_object buf;
static void dump_mode(drmModeModeInfo *mode)
{
printf(" %s %d %d %d %d %d %d %d %d %d %d",
mode->name,
mode->vrefresh,
mode->hdisplay,
mode->hsync_start,
mode->hsync_end,
mode->htotal,
mode->vdisplay,
mode->vsync_start,
mode->vsync_end,
mode->vtotal,
mode->clock);
printf("\n");
}
static int modeset_create_fb(int fd, struct buffer_object *bo)
{
struct drm_mode_create_dumb create = {};
struct drm_mode_map_dumb map = {};
create.width = bo->width;
create.height = bo->height;
create.bpp = 32;
drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &create);
bo->pitch = create.pitch;
bo->size = create.size;
bo->handle = create.handle;
drmModeAddFB(fd, bo->width, bo->height, 24, 32, bo->pitch,
bo->handle, &bo->fb_id);
map.handle = create.handle;
drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &map);
bo->vaddr = mmap(0, create.size, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, map.offset);
memset(bo->vaddr, 0xff, bo->size/2);
memset(bo->vaddr + bo->size/2, 0x88, bo->size/2);
return 0;
}
static uint32_t get_property_id(int fd, drmModeObjectProperties *props,
const char *name)
{
drmModePropertyPtr property;
uint32_t i, id = 0;
for (i = 0; i < props->count_props; i++) {
property = drmModeGetProperty(fd, props->props[i]);
if (!strcmp(property->name, name))
id = property->prop_id;
drmModeFreeProperty(property);
if (id)
break;
}
return id;
}
int main(int argc, char **argv)
{
int drm_fd;
drmModeRes *res;
drmModePlaneRes *plane_res;
drmModeConnector *conn;
drmModeObjectProperties *props;
int crtc_id;
int conn_id;
int plane_id;
int property_temp;
uint32_t blob_id;
drmModeAtomicReqPtr req = NULL;
drm_fd = open("/dev/dri/card0", O_RDWR | O_CLOEXEC);
if (drm_fd < 0) {
printf("open card error\n");
return 0;
}
res = drmModeGetResources(drm_fd);
if (!res) {
printf("getresource error\n");
return 0;
}
crtc_id = res->crtcs[0];
conn_id = res->connectors[1];
drmSetClientCap(drm_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
plane_res = drmModeGetPlaneResources(drm_fd);
plane_id = plane_res->planes[1];
printf("plane%d, crtc%d, conn%d\n", plane_id, crtc_id, conn_id);
conn = drmModeGetConnector(drm_fd, conn_id);
if (!conn) {
printf("get conn error\n");
return 0;
}
if (conn->count_modes) {
printf("print mode counts %d\n", conn->count_modes);
for (int i = 0; i < conn->count_modes; i++) {
dump_mode(&conn->modes[i]);
buf.width = conn->modes[i].hdisplay;
buf.height = conn->modes[i].vdisplay;
}
}
modeset_create_fb(drm_fd, &buf);
drmSetClientCap(drm_fd, DRM_CLIENT_CAP_ATOMIC, 1);
req = drmModeAtomicAlloc();
props = drmModeObjectGetProperties(drm_fd, conn_id, DRM_MODE_OBJECT_CONNECTOR);
property_temp = get_property_id(drm_fd, props, "CRTC_ID");
drmModeAtomicAddProperty(req, conn_id, property_temp, crtc_id);
drmModeFreeObjectProperties(props);
drmModeCreatePropertyBlob(drm_fd, &conn->modes[0], sizeof(conn->modes[0]), &blob_id);
props = drmModeObjectGetProperties(drm_fd, crtc_id, DRM_MODE_OBJECT_CRTC);
property_temp = get_property_id(drm_fd, props, "ACTIVE");
drmModeAtomicAddProperty(req, crtc_id, property_temp, 1);
property_temp = get_property_id(drm_fd, props, "MODE_ID");
drmModeAtomicAddProperty(req, crtc_id, property_temp, blob_id);
drmModeFreeObjectProperties(props);
props = drmModeObjectGetProperties(drm_fd, plane_id, DRM_MODE_OBJECT_PLANE);
property_temp = get_property_id(drm_fd, props, "CRTC_ID");
drmModeAtomicAddProperty(req, plane_id, property_temp, crtc_id);
property_temp = get_property_id(drm_fd, props, "FB_ID");
drmModeAtomicAddProperty(req, plane_id, property_temp, buf.fb_id);
property_temp = get_property_id(drm_fd, props, "CRTC_X");
drmModeAtomicAddProperty(req, plane_id, property_temp, 0);
property_temp = get_property_id(drm_fd, props, "CRTC_Y");
drmModeAtomicAddProperty(req, plane_id, property_temp, 0);
property_temp = get_property_id(drm_fd, props, "CRTC_W");
drmModeAtomicAddProperty(req, plane_id, property_temp, 1920);
property_temp = get_property_id(drm_fd, props, "CRTC_H");
drmModeAtomicAddProperty(req, plane_id, property_temp, 1080);
property_temp = get_property_id(drm_fd, props, "SRC_X");
drmModeAtomicAddProperty(req, plane_id, property_temp, 0);
property_temp = get_property_id(drm_fd, props, "SRC_Y");
drmModeAtomicAddProperty(req, plane_id, property_temp, 0);
property_temp = get_property_id(drm_fd, props, "SRC_W");
drmModeAtomicAddProperty(req, plane_id, property_temp, 1920<<16);
property_temp = get_property_id(drm_fd, props, "SRC_H");
drmModeAtomicAddProperty(req, plane_id, property_temp, 1080<<16);
drmModeFreeObjectProperties(props);
drmModeAtomicCommit(drm_fd, req, DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_ATOMIC_ALLOW_MODESET , NULL);
getchar();
drmModeFreeConnector(conn);
drmModeFreePlaneResources(plane_res);
drmModeFreeResources(res);
close(drm_fd);
return 0;
}
1.
drm_public drmModeResPtr drmModeGetResources(int fd)
drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res) //调用ioctl,填充返回的drmModeResPtr
DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, 0), //kernel实现