zoukankan      html  css  js  c++  java
  • linux DRM driver 使用示例【转】

    转自:https://www.jianshu.com/p/f41f98a40455

    DRM实例教程

    DRM是一个显示驱动框架,也就是把功能封装成 open/close/ioctl 等标准接口,应用程序调用这些接口来驱动设备,显示数据。我们这里将从使用的角度来看看,怎么验证和使用DRM驱动。

    DRM设备节点

    DRM驱动会在/dev/dri下创建3个设备节点:

    card0
    controlD64
    renderD128
    

    libdrm库

    DRM驱动,对用户空间,提供了专门的的调用库libdrm.so,用户空间通过该库可以间接的调用和使用驱动。

    打开设备

        int fd = open("/dev/dri/card0", O_RDWR | O_CLOEXEC);
        if (fd < 0) {
            ret = -errno;
            fprintf(stderr, "cannot open '%s': %m
    ", 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
    ",
                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
    ",
                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
    ",
                    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
    ",
                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
    ",
                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
    ",
                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
    ",
                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
    来源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 相关阅读:
    CentOS虚拟机和物理机共享文件夹实现
    集训第六周 数学概念与方法 概率 数论 最大公约数 G题
    集训第六周 数学概念与方法 概率 F题
    集训第六周 E题
    集训第六周 古典概型 期望 D题 Discovering Gold 期望
    集训第六周 古典概型 期望 C题
    集训第六周 数学概念与方法 UVA 11181 条件概率
    集训第六周 数学概念与方法 UVA 11722 几何概型
    DAG模型(矩形嵌套)
    集训第五周 动态规划 K题 背包
  • 原文地址:https://www.cnblogs.com/sky-heaven/p/12304291.html
Copyright © 2011-2022 走看看