當前位置:
首頁 >
DRM实例教程
發布時間:2024/9/27
49
豆豆
DRM實例教程
DRM是一個顯示驅動框架,也就是把功能封裝成 open/close/ioctl 等標準接口,應用程序調用這些接口來驅動設備,顯示數據。我們這里將從使用的角度來看看,怎么驗證和使用DRM驅動。
DRM設備節點
DRM驅動會在/dev/dri下創建3個設備節點:
?
card0 controlD64 renderD128libdrm庫
DRM驅動,對用戶空間,提供了專門的的調用庫libdrm.so,用戶空間通過該庫可以間接的調用和使用驅動。
打開設備
?
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;}打開設備有專門的接口:drmOpen
檢查DRM的能力
DRM的能力通過drmGetCap接口獲取,用drm_get_cap結構描述:
?
/** 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的獲取需要兩次,第一次,獲取數量大小,第二次才真正獲取具體的Resource。具體看這個函數:
?
drmModeResPtr drmModeGetResources(int fd)Resource結構封裝:
?
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;實例
?
/* retrieve resources */int ret = drmModeGetResources(fd);if (!res) {fprintf(stderr, "cannot retrieve DRM resources (%d): %m\n",errno);return -errno;}獲取Connector
_drmModeConnector描述結構:
?
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的結構描述:
?
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結構描述:
?
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
創建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;}準備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的準備
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實例:
how-to代碼實例
作者:夕月風
鏈接:https://www.jianshu.com/p/f41f98a40455
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
總結
- 上一篇: 宁波鄞州区宁波市房价多少?
- 下一篇: 3DSlicer相关资料汇总