日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

DRM实例教程

發(fā)布時(shí)間:2024/9/27 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 DRM实例教程 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

DRM實(shí)例教程

DRM是一個(gè)顯示驅(qū)動(dòng)框架,也就是把功能封裝成 open/close/ioctl 等標(biāo)準(zhǔn)接口,應(yīng)用程序調(diào)用這些接口來驅(qū)動(dòng)設(shè)備,顯示數(shù)據(jù)。我們這里將從使用的角度來看看,怎么驗(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 renderD128

libdrm庫

DRM驅(qū)動(dòng),對(duì)用戶空間,提供了專門的的調(diào)用庫libdrm.so,用戶空間通過該庫可以間接的調(diào)用和使用驅(qū)動(dòng)。

打開設(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;}

打開設(shè)備有專門的接口:drmOpen

檢查DRM的能力

DRM的能力通過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
來源:簡書
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。

總結(jié)

以上是生活随笔為你收集整理的DRM实例教程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。