DRM实例教程
DRM實(shí)例教程
DRM是一個(gè)顯示驅(qū)動(dòng)框架,也就是把功能封裝成 open/close/ioctl 等標(biāo)準(zhǔn)接口,應(yīng)用程序調(diào)用這些接口來(lái)驅(qū)動(dòng)設(shè)備,顯示數(shù)據(jù)。我們這里將從使用的角度來(lái)看看,怎么驗(yàn)證和使用DRM驅(qū)動(dòng)。
DRM設(shè)備節(jié)點(diǎn)
DRM驅(qū)動(dòng)會(huì)在/dev/dri下創(chuàng)建3個(gè)設(shè)備節(jié)點(diǎn):
?
card0 controlD64 renderD128libdrm庫(kù)
DRM驅(qū)動(dòng),對(duì)用戶(hù)空間,提供了專(zhuān)門(mén)的的調(diào)用庫(kù)libdrm.so,用戶(hù)空間通過(guò)該庫(kù)可以間接的調(diào)用和使用驅(qū)動(dòng)。
打開(kāi)設(shè)備
?
int fd = open("/dev/dri/card0", O_RDWR | O_CLOEXEC);if (fd < 0) {ret = -errno;fprintf(stderr, "cannot open '%s': %m\n", node);return ret;}打開(kāi)設(shè)備有專(zhuān)門(mén)的接口:drmOpen
檢查DRM的能力
DRM的能力通過(guò)drmGetCap接口獲取,用drm_get_cap結(jié)構(gòu)描述:
?
/** DRM_IOCTL_GET_CAP ioctl argument type */ struct drm_get_cap {__u64 capability;__u64 value; };int drmGetCap(int fd, uint64_t capability, uint64_t *value) {struct drm_get_cap cap;int ret;memclear(cap);cap.capability = capability;ret = drmIoctl(fd, DRM_IOCTL_GET_CAP, &cap);if (ret)return ret;*value = cap.value;return 0; }使用示例:
?
uint64_t has_dumb;if (drmGetCap(fd, DRM_CAP_DUMB_BUFFER, &has_dumb) < 0 ||!has_dumb) {fprintf(stderr, "drm device '%s' does not support dumb buffers\n",node);close(fd);return -EOPNOTSUPP;}檢索Resource
Resource的獲取需要兩次,第一次,獲取數(shù)量大小,第二次才真正獲取具體的Resource。具體看這個(gè)函數(shù):
?
drmModeResPtr drmModeGetResources(int fd)Resource結(jié)構(gòu)封裝:
?
struct drm_mode_card_res {__u64 fb_id_ptr;__u64 crtc_id_ptr;__u64 connector_id_ptr;__u64 encoder_id_ptr;__u32 count_fbs;__u32 count_crtcs;__u32 count_connectors;__u32 count_encoders;__u32 min_width, max_width;__u32 min_height, max_height; };?
typedef struct _drmModeRes {int count_fbs;uint32_t *fbs;int count_crtcs;uint32_t *crtcs;int count_connectors;uint32_t *connectors;int count_encoders;uint32_t *encoders;uint32_t min_width, max_width;uint32_t min_height, max_height; } drmModeRes, *drmModeResPtr;實(shí)例
?
/* retrieve resources */int ret = drmModeGetResources(fd);if (!res) {fprintf(stderr, "cannot retrieve DRM resources (%d): %m\n",errno);return -errno;}獲取Connector
_drmModeConnector描述結(jié)構(gòu):
?
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;示例:
?
drmModeConnector *conn = drmModeGetConnector(fd, res->connectors[i]);if (!conn) {fprintf(stderr, "cannot retrieve DRM connector %u:%u (%d): %m\n",i, res->connectors[i], errno);continue;}Encoder
Encoder的結(jié)構(gòu)描述:
?
typedef struct _drmModeEncoder {uint32_t encoder_id;uint32_t encoder_type;uint32_t crtc_id;uint32_t possible_crtcs;uint32_t possible_clones; } drmModeEncoder, *drmModeEncoderPtr;示例:
?
if (conn->encoder_id)drmModeEncoder *enc = drmModeGetEncoder(fd, conn->encoder_id);}?
drmModeEncoderPtr drmModeGetEncoder(int fd, uint32_t encoder_id) {struct drm_mode_get_encoder enc;drmModeEncoderPtr r = NULL;memclear(enc);enc.encoder_id = encoder_id;if (drmIoctl(fd, DRM_IOCTL_MODE_GETENCODER, &enc))return 0;if (!(r = drmMalloc(sizeof(*r))))return 0;r->encoder_id = enc.encoder_id;r->crtc_id = enc.crtc_id;r->encoder_type = enc.encoder_type;r->possible_crtcs = enc.possible_crtcs;r->possible_clones = enc.possible_clones;return r; }crtc
CRTC結(jié)構(gòu)描述:
?
struct crtc {drmModeCrtc *crtc;drmModeObjectProperties *props;drmModePropertyRes **props_info;drmModeModeInfo *mode; };?
typedef struct _drmModeCrtc {uint32_t crtc_id;uint32_t buffer_id; /**< FB id to connect to 0 = disconnect */uint32_t x, y; /**< Position on the framebuffer */uint32_t width, height;int mode_valid;drmModeModeInfo mode;int gamma_size; /**< Number of gamma stops */} drmModeCrtc, *drmModeCrtcPtr;FrameBuffer
創(chuàng)建DUMB Buffer
?
ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &creq);if (ret < 0) {fprintf(stderr, "cannot create dumb buffer (%d): %m\n",errno);return -errno;}添加FB
?
/* create framebuffer object for the dumb-buffer */ret = drmModeAddFB(fd, dev->width, dev->height, 24, 32, dev->stride,dev->handle, &dev->fb);if (ret) {fprintf(stderr, "cannot create framebuffer (%d): %m\n",errno);ret = -errno;goto err_destroy;}準(zhǔn)備map
?
/* prepare buffer for memory mapping */memset(&mreq, 0, sizeof(mreq));mreq.handle = dev->handle;ret = drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &mreq);if (ret) {fprintf(stderr, "cannot map dumb buffer (%d): %m\n",errno);ret = -errno;goto err_fb;}做map操作:
?
/* perform actual memory mapping */dev->map = mmap(0, dev->size, PROT_READ | PROT_WRITE, MAP_SHARED,fd, mreq.offset);if (dev->map == MAP_FAILED) {fprintf(stderr, "cannot mmap dumb buffer (%d): %m\n",errno);ret = -errno;goto err_fb;}CRTC的準(zhǔn)備
drmModeGetCrtc
drmModeSetCrtc
?
drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId) {struct drm_mode_crtc crtc;drmModeCrtcPtr r;memclear(crtc);crtc.crtc_id = crtcId;if (drmIoctl(fd, DRM_IOCTL_MODE_GETCRTC, &crtc))return 0;/** return*/if (!(r = drmMalloc(sizeof(*r))))return 0;r->crtc_id = crtc.crtc_id;r->x = crtc.x;r->y = crtc.y;r->mode_valid = crtc.mode_valid;if (r->mode_valid) {memcpy(&r->mode, &crtc.mode, sizeof(struct drm_mode_modeinfo));r->width = crtc.mode.hdisplay;r->height = crtc.mode.vdisplay;}r->buffer_id = crtc.fb_id;r->gamma_size = crtc.gamma_size;return r; }int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId,uint32_t x, uint32_t y, uint32_t *connectors, int count,drmModeModeInfoPtr mode) {struct drm_mode_crtc crtc;memclear(crtc);crtc.x = x;crtc.y = y;crtc.crtc_id = crtcId;crtc.fb_id = bufferId;crtc.set_connectors_ptr = VOID2U64(connectors);crtc.count_connectors = count;if (mode) {memcpy(&crtc.mode, mode, sizeof(struct drm_mode_modeinfo));crtc.mode_valid = 1;}return DRM_IOCTL(fd, DRM_IOCTL_MODE_SETCRTC, &crtc); }繪制
?
static void modeset_draw(void) {uint8_t r, g, b;bool r_up, g_up, b_up;unsigned int i, j, k, off;struct modeset_dev *iter;srand(time(NULL));r = rand() % 0xff;g = rand() % 0xff;b = rand() % 0xff;r_up = g_up = b_up = true;for (i = 0; i < 50; ++i) {r = next_color(&r_up, r, 20);g = next_color(&g_up, g, 10);b = next_color(&b_up, b, 5);for (iter = modeset_list; iter; iter = iter->next) {for (j = 0; j < iter->height; ++j) {for (k = 0; k < iter->width; ++k) {off = iter->stride * j + k * 4;*(uint32_t*)&iter->map[off] =(r << 16) | (g << 8) | b;}}}usleep(100000);} }具體的代碼,可以參考how-to實(shí)例:
how-to代碼實(shí)例
作者:夕月風(fēng)
鏈接:https://www.jianshu.com/p/f41f98a40455
來(lái)源:簡(jiǎn)書(shū)
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。
總結(jié)
- 上一篇: 宁波鄞州区宁波市房价多少?
- 下一篇: 热水器泄压阀排水管如何安装