上节讲到《DRM驱动(四)之ADD_FB》调用drmModeAddFB创建drm_framebuffer。然后通过

drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &map);

vaddr = mmap(0, create.size, PROT_READ | PROT_WRITE,MAP_SHARED, fd, map.offset);

将物理地址map到用户空间后,就可以在这块内存上绘一张自己喜欢的图。接下来就需要把这块内存配置到硬件上面,进行刷图。

刷图有很多中方式,比如:

int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId, uint32_t x, uint32_t y, uint32_t *connectors, int count, drmModeModeInfoPtr mode)

fd:文件描述符

crtcId:crtc_id

bufferId:即上节创建的fb id

x,y:在屏幕上的显示坐标

connectors:connector id

count:connector 数量

mode:包括刷新率,分辨率等timing的信息

也可以使用下面接口:

drmModeAtomicAlloc();

drmModeAtomicAddProperty(..., property_id, property_value);

drmModeAtomicCommit(...);

本节以drmModeSetCrtc为例

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);
}

主要用于填充如下数据结构,传给内核,drm会根据传入的信息配置display硬件。比如crtc_id来指定显示到哪个crtc,fb_id指定哪块使用dumb显存等等。

struct drm_mode_crtc {
__u64 set_connectors_ptr;
__u32 count_connectors;
__u32 crtc_id; /**< Id */
__u32 fb_id; /**< Id of framebuffer */__u32 x; /**< x Position on the framebuffer */
__u32 y; /**< y Position on the framebuffer */__u32 gamma_size;
__u32 mode_valid;
struct drm_mode_modeinfo mode;
}

按照之前的经验,在内核drm_ioctl.c中找到对应函数调用

DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED)

DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATOMIC, drm_mode_atomic_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED)

drm_mode_setcrtc和drm_mode_atomic_ioctl从函数调用来看都会调用drm_atomic_commit(state) 也就是说应用传入的参数最终会转换成struct drm_atomic_state;

看下struct drm_atomic_state数据结构

struct drm_atomic_state {struct kref ref;struct drm_device *dev;bool allow_modeset : 1;bool legacy_cursor_update : 1;bool async_update : 1;struct __drm_planes_state *planes;struct __drm_crtcs_state *crtcs;int num_connector;struct __drm_connnectors_state *connectors;int num_private_objs;struct __drm_private_objs_state *private_objs;struct drm_modeset_acquire_ctx *acquire_ctx;struct work_struct commit_work;
};

drm_atomic_state和其他组件state的继承关系如下图:

数据结构之间的转换过程:

int drm_mode_setcrtc(struct drm_device *dev, void *data,struct drm_file *file_priv)
{crtc = drm_crtc_find(dev, file_priv, crtc_req->crtc_id);if (crtc_req->mode_valid) {fb = drm_framebuffer_lookup(dev, file_priv, crtc_req->fb_id);mode = drm_mode_create(dev);ret = drm_mode_convert_umode(mode, &crtc_req->mode);}if (crtc_req->count_connectors > 0) {connector_set = kmalloc_array(crtc_req->count_connectors,sizeof(struct drm_connector *),GFP_KERNEL);for (i = 0; i < crtc_req->count_connectors; i++) {connector_set[i] = NULL;set_connectors_ptr = (uint32_t __user *)(unsigned long)crtc_req->set_connectors_ptr;connector = drm_connector_lookup(dev, file_priv, out_id);connector_set[i] = connector;}}set.crtc = crtc;set.x = crtc_req->x;set.y = crtc_req->y;set.mode = mode;set.connectors = connector_set;set.num_connectors = crtc_req->count_connectors;set.fb = fb;ret = __drm_mode_set_config_internal(&set, &ctx);out:if (fb)drm_framebuffer_put(fb);if (connector_set) {for (i = 0; i < crtc_req->count_connectors; i++) {if (connector_set[i])drm_connector_put(connector_set[i]);}}kfree(connector_set);drm_mode_destroy(dev, mode);return ret;
}

drm_mode_setcrtc的主要作用:

  1. 根据应用传入的crtc_id找到crtc
  2. 根据应用传入的fb_id,找到对应的drm_framebuffer
  3. 根据应用传入的mode,创建一个drm_display_mode
  4. 根据传入的set_connectors_ptr,找到驱动对应的connector
  5. 将以上信息转为struct drm_mode_set并调用__drm_mode_set_config_internal
static int __drm_mode_set_config_internal(struct drm_mode_set *set,struct drm_modeset_acquire_ctx *ctx)
{struct drm_crtc *crtc = set->crtc;struct drm_framebuffer *fb;struct drm_crtc *tmp;drm_for_each_crtc(tmp, crtc->dev)tmp->primary->old_fb = tmp->primary->fb;fb = set->fb;ret = drm_atomic_helper_set_config(set, ctx);if (ret == 0) {crtc->primary->crtc = crtc;crtc->primary->fb = fb;}return ret;
}

__drm_mode_set_config_internal的内容比较少,主要调用drm_atomic_helper_set_config

int drm_atomic_helper_set_config(struct drm_mode_set *set,struct drm_modeset_acquire_ctx *ctx)
{struct drm_atomic_state *state;struct drm_crtc *crtc = set->crtc;int ret = 0;state = drm_atomic_state_alloc(crtc->dev);ret = __drm_atomic_helper_set_config(set, state);ret = drm_atomic_commit(state);
fail:drm_atomic_state_put(state);return ret;
}

drm_atomic_helper_set_config的主要作用:

  1. 创建struct drm_atomic_state
  2. 将struct drm_mode_set转换成为struct drm_atomic_state
  3. 调用drm_atomic_commit 将修改commit到硬件
int __drm_atomic_helper_set_config(struct drm_mode_set *set,struct drm_atomic_state *state)
{struct drm_crtc_state *crtc_state;struct drm_plane_state *primary_state;struct drm_crtc *crtc = set->crtc;int hdisplay, vdisplay;int ret;crtc_state = drm_atomic_get_crtc_state(state, crtc);primary_state = drm_atomic_get_plane_state(state, crtc->primary);ret = drm_atomic_set_mode_for_crtc(crtc_state, set->mode);crtc_state->active = true;ret = drm_atomic_set_crtc_for_plane(primary_state, crtc);drm_mode_get_hv_timing(set->mode, &hdisplay, &vdisplay);drm_atomic_set_fb_for_plane(primary_state, set->fb);primary_state->crtc_x = 0;primary_state->crtc_y = 0;primary_state->crtc_w = hdisplay;primary_state->crtc_h = vdisplay;primary_state->src_x = set->x << 16;primary_state->src_y = set->y << 16;if (drm_rotation_90_or_270(primary_state->rotation)) {primary_state->src_w = vdisplay << 16;primary_state->src_h = hdisplay << 16;} else {primary_state->src_w = hdisplay << 16;primary_state->src_h = vdisplay << 16;}ret = update_output_state(state, set);return 0;
}

这块比较代码有点复杂,这里简单的用一个表格说明几个比较重要的结构体数据之间的对应关系,不再赘述代码里的内容。

本节介绍了应用调用drmModeSetCrtc时传入参数转换为struct drm_atomic_state的过程,下节将介绍drm利用drm_atomic_state中内容更新图像的过程。

注:文中代码仅作说明,删除了一些错误处理等内容,介意可以看下drm驱动的源码。

DRM驱动(五)之drm_atomic_state相关推荐

  1. DRM驱动(六)之atomic_check

    上节聊到应用传下来的参数均被存到对应的state.为了使驱动的容错能力比较强,在更新到硬件寄存器之前还需要进行一系列的参数检查,比如要显示图像的大小是否会超过支持分辨率,如果超过了显示的硬件可能会异常 ...

  2. DRM驱动代码分析:图层参数更新

    前言: 无业居家,闭门造车.非常欢迎大家帮忙指正. 有些代码流程是看代码分析的,没有去验证是否正确 我对DRM框架的很多东西都不了解,所以有些地方会比较生硬.熟悉学习需要时间,文章一直堆在草稿箱可能会 ...

  3. fb驱动安装linux系统,drm 驱动是如何创建 fb device 的

    drm 驱动是如何创建 fb device 的 什么是 drm? drm 是一个 Linux 内核的显示系统驱动框架,区别于另外一个 DRM数字版权保护 drm 是一个管理 GPU 的显示框架 在内核 ...

  4. DRM驱动(三)之CREATE_DUMB

    上节讲到显示处理器会将一块含有图像数据的memory进行处理后送到下一级.后面几节我会根据龙哥的<最简单的DRM应用程序>一步一步分析用户调用的接口在drm驱动中有怎么样的处理. DRM驱 ...

  5. i2c 驱动五:gpio模拟i2c

    有关linux的i2c相关文章有一下几篇,他们互相关联,应该一同看: - i2c 驱动一:简介 - i2c 驱动二:devfs文件系统 - i2c 驱动三:自己实现设备和驱动分离 - i2c 驱动四: ...

  6. DRM驱动(二)之DRM驱动模块简介

    上节在<显示处理器介绍>中阐述了显示处理器的大致功能以及要配置的参数:本节将介绍一下DRM驱动中的模块与显示处理器的关系. 做过显示的都知道,目前大多数厂商已经抛弃fb框架,使用drm驱动 ...

  7. 《DRM 专栏》| 彻底入门 DRM 驱动

    https://cloud.tencent.com/developer/article/2021477 前面的 DRM 应用程序系列文章中,我们学习了如何使用 libdrm 接口编写 DRM 应用程序 ...

  8. DRM框架(vkms)分析(9)----drm驱动创建fbdevice分析(以rockchip_drm_drv为例)

    本文主要介绍DRM框架里的fbdev兼容逻辑 一 framebuffer框架简单介绍 framebuffer框架下fbdev的注册主要三步步: (1)创建fbdev操作函数,以rockchip为例: ...

  9. DRM驱动(一)之显示处理器介绍

    显示处理器是什么 将在内存中的图像数据,转化为电信号送到显示设备称为显示控制器,比如早期的LCDC.后面进行了拓展,可以处理一些简单的图像,比如缩放.旋转.合成等,如瑞芯的vop,高通的sde称为显示 ...

最新文章

  1. 东莞网络推广浅析如何通过简化标题来提升核心关键词排名能力呢?
  2. pass4side IBM 000-M15
  3. 【白皮书下载】《追本数源•开启产品智能化时代》| 产品指数级增长手册
  4. hihoCoder1233(2015北京网络赛H题)
  5. flex java_Flex与Java通信 (一)
  6. 【ASP.NET Core】处理异常
  7. 三层加过的注释java_spring框架中三层架构相关的注解
  8. C++|Java混合实验-Spring Boot获取客户端操作系统,浏览器,Ip等信息,Qt端展示
  9. php操作xml类,PHP实现的XML操作类【XML Library】
  10. bgp 建立邻居发送的报文_OSPF报文,SPF算法,邻居关系建立及排错,理论+实战
  11. 一加10 Pro的性能配置还是非常不错的
  12. 爱情九十三课,指尖情话
  13. CentOS启动报错:Centos kernel panic-not syncing:VFS:Unable to mount root fs on unknown block
  14. Web Components 系列(五)—— 关于 Templates
  15. 方差分析软件_Minitab统计软件入门(一)
  16. excel自动调整列宽_EXCEL选择性粘贴,这些招数你用过吗?
  17. 剑指Offer28.对称的二叉树
  18. 怎样设计一个好的社交网站
  19. 《长安十二时辰》,作为程序员,看完我震惊了!
  20. [Algorithmic Toolbox学习笔记][week6]Placing Parentheses

热门文章

  1. 逆势而上,Intel大连工厂高价挖人
  2. win10更新后任务栏卡死解决方法
  3. Vue和layUI的区别何在?
  4. HEVC帧内预测参考像素检测获取和滤波
  5. mfc,WM_CTLCOLOR,WM_PAINT
  6. 空格折叠(幽灵折叠)
  7. 简述思科、华为交换机型号字母代表的意思
  8. 安装NVIDIA显卡驱动以及CUDA
  9. 【CV】Reg2Net:一种用于计算机视觉任务的多尺度骨干架构
  10. 解决 vmware 虚拟机安装后没有虚拟网卡问题