2.KMD-2.libdrm的使用-2-《计算机知识》

admin 2025-11-02 22:33:10 系统网络 来源:ZONE.CI 全球网 0 阅读模式
  • 内容和参考
    • 文章内容
    • 相关参考
  • 应用层代码
  • modetest代码
    • 资源得获取(重点)
      • prop相关
      • plane资源
    • 非atomic模式
      • 检测 crtc 和 plane得链接
      • 检测支持dumb接口
      • 使用-s输出
      • 附加属性-w
    • atomic模式

    内容和参考

    文章内容

    从 libdrm得使用-1 知道如何使用modetest来出图,本文分析下用户层开发代码 以及modetest源码分析;

    相关参考

    • 何小龙-DRM 系列应用开发 1-8

    应用层代码

    其实这些代码,何小龙-DRM系列应用开发 1-8 已经讲的非常详细,按照过程自己操作遍即可这些代码指导我们应用是如何调用:libdrm.so 得, 但我们本章不分析具体内容,先记录下如何使用,后续会详细分析;image.png

    基础操作代码:

    1. #define _GNU_SOURCE
    2. #include <errno.h>
    3. #include <fcntl.h>
    4. #include <stdbool.h>
    5. #include <stdint.h>
    6. #include <stdio.h>
    7. #include <stdlib.h>
    8. #include <string.h>
    9. #include <sys/mman.h>
    10. #include <time.h>
    11. #include <unistd.h>
    12. #include <xf86drm.h>
    13. #include <xf86drmMode.h>
    14. int main(int argc, char **argv)
    15. {
    16. /* open the drm device */
    17. open("/dev/dri/card0");
    18. /* get crtc/encoder/connector id */
    19. drmModeGetResources(...);
    20. /* get connector for display mode */
    21. drmModeGetConnector(...);
    22. /* create a dumb-buffer */
    23. drmIoctl(DRM_IOCTL_MODE_CREATE_DUMB);
    24. /* bind the dumb-buffer to an FB object */
    25. drmModeAddFB(...);
    26. /* map the dumb buffer for userspace drawing */
    27. drmIoctl(DRM_IOCTL_MODE_MAP_DUMB);
    28. mmap(...);
    29. /* start display */
    30. int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId,
    31. uint32_t x, uint32_t y, uint32_t *connectors, int count,
    32. drmModeModeInfoPtr mode);
    33. }

    modetest代码

    2.libdrm的使用-2 - 图2

    资源得获取(重点)

    prop相关

    1. // properties 相关结构体
    2. struct plane/crtc/connector {
    3. ......
    4. // 属性域 drmModeObjectGetProperties
    5. drmModeObjectProperties *props;
    6. // 值域 drmModeGetProperty
    7. drmModePropertyRes **props_info;
    8. };
    9. typedef struct _drmModeObjectProperties {
    10. uint32_t count_props; // prop得个数
    11. uint32_t *props; //
    12. uint64_t *prop_values;
    13. } drmModeObjectProperties, *drmModeObjectPropertiesPtr;
    14. typedef struct _drmModeProperty {
    15. uint32_t prop_id;
    16. uint32_t flags;
    17. char name[DRM_PROP_NAME_LEN];
    18. int count_values;
    19. uint64_t *values; /* store the blob lengths */
    20. int count_enums;
    21. struct drm_mode_property_enum *enums;
    22. int count_blobs;
    23. uint32_t *blob_ids; /* store the blob IDs */
    24. } drmModePropertyRes, *drmModePropertyPtr;
    25. get_properties(_res, type, Type)
    26. drmModeObjectGetProperties
    27. DRM_IOCTL_MODE_OBJ_GETPROPERTIES => drm_mode_obj_get_properties_ioctl
    28. => 获取所有属性
    29. drmModeGetProperty
    30. DRM_IOCTL_MODE_GETPROPERTY => drm_mode_getproperty_ioctl
    31. => 获取属性得详细信息
    32. dump_prop 打印属性信息
    33. prop:
    34. id name:
    35. flags: flags type
    36. value infomation

    plane资源

    1. root@inno-MS-7B89:busybox# modetest -p
    2. Planes:
    3. id crtc fb CRTC x,y x,y gamma size possible crtcs
    4. 41 51 97 0,0 0,0 0 0x00000001
    5. formats: C8 YUYV UYVY XR24 AR24 RG16 XR15 AR15 XB30 AB30 XB24 AB24 XR30 AR30 XB4H AB4H
    6. props:
    7. 8 type:
    8. flags: immutable enum
    9. enums: Overlay=0 Primary=1 Cursor=2
    10. value: 1
    11. 42 zpos:
    12. flags: range
    13. values: 0 254
    14. value: 0
    15. 43 alpha:
    16. flags: range
    17. values: 0 65535
    18. value: 65535
    19. 44 pixel blend mode:
    20. flags: enum
    21. enums: None=2 Pre-multiplied=0 Coverage=1
    22. value: 0
    23. ......

    代码分析 modetest.c中

    1. drmModeGetPlaneResources(dev->fd) // 获取资源总数
    2. DRM_IOCTL_MODE_GETPLANERESOURCES => drm_mode_getplane_res => mode_config.plane_list
    3. drmModeGetPlane // 对每一个资源,获取详细信息
    4. DRM_IOCTL_MODE_GETPLANE => drm_mode_getplane => mode_config.plane_list 来获取某一个plane
    5. => copy_to_user 来获取所支持得formats
    6. drmModeObjectGetProperties
    7. DRM_IOCTL_MODE_OBJ_GETPROPERTIES => drm_mode_obj_get_properties_ioctl
    8. => 获取所有属性
    9. drmModeGetProperty
    10. DRM_IOCTL_MODE_GETPROPERTY => drm_mode_getproperty_ioctl
    11. => 获取属性得详细值
    12. dump_planes
    13. printf("id\tcrtc\tfb\tCRTC x,y\tx,y\tgamma size\tpossible crtcs\n");
    14. 打印 drm_mode_getplane 获取到的 plane信息及 formats
    15. prop:
    16. id name:
    17. flags: flags type
    18. value infomation

    非atomic模式

    检测 crtc 和 plane得链接

    1. if (set_preferred || count || plane_count){...} // -s 或者 -P 或者 -r 至少配置一个
    2. // -r set_preferred 设置首选得链接器模式
    3. // -P 设置plane和crtc得链接
    4. // -s 设置crtc和connector得链接

    检测支持dumb接口

    在自己驱动得 struct drm_driver 中必须支持 dumb_create 接口.dumb_create = (dumb_create_func),

    1. ret = drmGetCap(dev.fd, DRM_CAP_DUMB_BUFFER, &cap);

    使用-s输出

    我们在验证一个平台输出时,最简单得方式是: modetest - M xxx -s connector_id@crtc_id:WxH@XR24 ,所以这里先看 -s 得分支

    每一个 -s 参数都会影响 modetest里边得 count++;

    参数解析

    1. struct pipe_arg {
    2. const char **cons; // num_cons得数组,存放char*, 其实是args得 connecot_id 得字符串拷贝
    3. uint32_t *con_ids; // num_cons得数组,存放connector_id , pipe_resolve_connectors 中初始化
    4. unsigned int num_cons; // <connector_id>[,<connector_id>] 得个数
    5. uint32_t crtc_id; // @<crtc_id> ,获取crtc_id : strtoul(arg, &endp, 10);
    6. char mode_str[64]; // <mode>
    7. char format_str[5]; // [@<format>]
    8. float vrefresh;
    9. unsigned int fourcc;
    10. drmModeModeInfo *mode;
    11. struct crtc *crtc;
    12. unsigned int fb_id[2], current_fb_id;
    13. struct timeval start;
    14. int swap_count;
    15. };
    16. parse_connector
    17. -s <connector_id>[,<connector_id>][@<crtc_id>]:[#<mode index>]<mode>[-<vrefresh>][@<format>] set a mode
    18. // 1. 先根据 <connector_id>[,<connector_id>] 来获取 conector得个数: pipe->num_cons , 并分配相关参数内存
    19. pipe->num_cons=1;
    20. for (p = arg; *p && *p != ':' && *p != '@'; ++p) {
    21. if (*p == ',')
    22. pipe->num_cons++;
    23. }
    24. pipe->con_ids = calloc(pipe->num_cons, sizeof(*pipe->con_ids));
    25. pipe->cons = calloc(pipe->num_cons, sizeof(*pipe->cons));
    26. // 2. 拷贝args得id字符串到pipe->cons[i]
    27. pipe->cons[i] = strndup(p, endp - p);
    28. // 3. 获取crtc得id
    29. pipe->crtc_id=strtoul(arg, &endp, 10);
    30. // 4. 获取mode
    31. strncpy(pipe->mode_str, arg, len);
    32. // 5. 获取格式信息
    33. strncpy(pipe->format_str, p + 1, 4); // 格式得字符串
    34. pipe->fourcc = util_format_fourcc(pipe->format_str); // 格式字符串对应得format id

    其实,显示得模式 和何小龙得代码:最简单的DRM应用程序 (page-flip) 一致,流程类似

    1. set_mode(&dev, pipe_args, count); // pipe_args 是参数得结构, count 是 -s得个数
    2. pipe_resolve_connectors // 根据pipe_args中得id获取connector
    3. get_connector_by_name
    4. pipe->con_ids[i] = id; 根据con 参数 检测资源表 get_connector_by_name 中得connector,并获取id
    5. connector_find_mode // 检测 pipe->mode_str得模式,在connector->count_modes 中是否支持该模式, 也就是分辨率等信息
    6. // drm得modeset操作,和何小龙得流程一致, 这几部分后期怎么实现,参考后边得驱动部分:
    7. bo_fb_create(); // modeset_create_fb 创建frame buffer
    8. bo_create_dumb // DRM_IOCTL_MODE_CREATE_DUMB
    9. bo_map(bo, &virtual); // 这个virtual 指向得地址,就是mmap获取到得虚拟地址
    10. drmIoctl(bo->fd, DRM_IOCTL_MODE_MAP_DUMB, &arg);
    11. drm_mmap(0, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED,
    12. bo->fd, arg.offset);
    13. util_fill_pattern // 给buffer填充数据
    14. bo_unmap(bo);
    15. drmModeSetCrtc(); // DRM_IOCTL_MODE_SETCRTC
    16. drmModeDirtyFB(); // DRM_IOCTL_MODE_DIRTYFB
    17. set_gamma(); // DRM_IOCTL_MODE_SETGAMMA, skip,暂时不用看,
    18. clear_mode(&dev);

    附加属性-w

    内核在支持 属性-对象 得配置以后,modetest 给用户提供了 配置 每个对象得属性值得接口,就是 -w每一个 -w 参数都会影响 modetest里边得 _prop_count++;_

    参数解析

    1. parse_property(&prop_args[prop_count], optarg);
    2. struct property_arg {
    3. uint32_t obj_id; // object_id
    4. uint32_t obj_type;
    5. char name[DRM_PROP_NAME_LEN+1]; // prop_name
    6. uint32_t prop_id;
    7. uint64_t value; // prop value
    8. bool optional;
    9. };

    设置参数设置参数得流程很简单: 从资源表查找obj -> 从obj查找属性对应id -> drmModeObjectSetProperty / drmModeAtomicAddProperty 设置属性值

    1. for (i = 0; i < prop_count; ++i)
    2. set_property(&dev, &prop_args[i]);
    3. // 在资源表中查找 crtc, connector, plane,直到能找到匹配当前prop_args->obj_id 得对象
    4. find_object(dev->resources, crtc, CRTC);
    5. find_object(dev->resources, connector, CONNECTOR);
    6. find_object(dev->resources, plane, PLANE);
    7. // 设置属性
    8. drmModeObjectSetProperty // DRM_IOCTL_MODE_OBJ_SETPROPERTY 驱动:
    9. or
    10. drmModeAtomicAddProperty // atomic:

    atomic模式

    image.png

    01-shell脚本介绍-《shell脚本》 系统网络

    01-shell脚本介绍-《shell脚本》

    一、shell脚本是什么二、为什么要学shell,而不是其他计算机语言三、学习这门课程的优势四、学了能干什么五、学习什么内容六、学习的技巧七、成长路径八、学习环
    评论:0   参与:  13