DRM框架(vkms)分析(6)---- plane初始化
一 drm_plane结构体
struct drm_plane {struct drm_device *dev;//挂载到&drm_mode_config.plane_liststruct list_head head;char *name;struct drm_modeset_lock mutex;//表示plane的mode对象, 其包含了plane的各种属性struct drm_mode_object base;/*** @possible_crtcs: pipes this plane can be bound to constructed from* drm_crtc_mask()*///绑定的crtcuint32_t possible_crtcs;//plane支持的fb像素format类型数组, format类型如DRM_FORMAT_ARGB8888uint32_t *format_types;//plane支持的fb像素format类型数组大小unsigned int format_count;bool format_default;//modifier数组,其存放的值如DRM_FORMAT_MOD_LINEAR/DRM_FORMAT_MOD_X_TILED等uint64_t *modifiers;unsigned int modifier_count;/*** @crtc:** Currently bound CRTC, only meaningful for non-atomic drivers. For* atomic drivers this is forced to be NULL, atomic drivers should* instead check &drm_plane_state.crtc.*//*no-atomic drivers用来标识当前绑定的crtc。 对于atomic driver,该值应该为null*并使用 &drm_plane_state.crtc替代*/struct drm_crtc *crtc;/*no-atomic drivers用来标识当前绑定的fb。 对于atomic driver,该值应该为null*并使用 &drm_plane_state.fb替代*/struct drm_framebuffer *fb;/*对于non-atomic drivers, old_fb用于在modeset操作时跟踪老的fb* atomic drivers下,该值为Null*/struct drm_framebuffer *old_fb;//plane funcsconst struct drm_plane_funcs *funcs;/** @properties: property tracking for this plane *///plane的属性struct drm_object_properties properties;//如DRM_PLANE_TYPE_OVERLAY/DRM_PLANE_TYPE_PRIMARY/DRM_PLANE_TYPE_CURSORenum drm_plane_type type;//mode_config.list中的序号unsigned index;const struct drm_plane_helper_funcs *helper_private;//表示plane的各种状态,如其绑定的crtc/fb等,用于atomic操作struct drm_plane_state *state;//这些属性待研究struct drm_property *alpha_property;struct drm_property *zpos_property;struct drm_property *rotation_property;struct drm_property *blend_mode_property;struct drm_property *color_encoding_property;struct drm_property *color_range_property;struct drm_property *scaling_filter_property;
};
二 drm_plane的初始化
vkms_plane_init//设置plane支持的fb formatsfromats = vkms_formats//设置plane->helper_privatefuncs = &vkms_primary_helper_funcsret = drm_universal_plane_init(dev, plane, 1<<index,&vkms_plane_funcs,formats, nformats,NULL, type, NULL);__drm_universal_plane_init//创建DRM_MODE_OBJECT_PLANE类型的drm_mode_object对象plane->baseret = drm_mode_object_add(dev, &plane->base, DRM_MODE_OBJECT_PLANE); //绑定base.properties到plane->propertiesplane->base.properties = &plane->propertiesplane->funs = funcs; // vkms_plane_funcs;//.... 设置format_types/ modifiers/ possible_crtcs等// 将dev->mode_config->prop_fb_id等属性绑定到plane->base中drm_obj_attack_property(....)//设置plane->helper_private = vkms_primary_helper_funcs drm_plane_helper_add(plane, funcs)
三 plane->funcs
/*** struct drm_plane_funcs - driver plane control functions*/
struct drm_plane_funcs {/*使能配置plane的crtc和framebuffer.src_x/src_y/src_w/src_h指定fb的源区域*crtc_x/crtc_y/crtc_w/crtc_h指定其显示在crtc上的目标区域*atomic操作使用drm_atomic_helper_update_plane实现*/int (*update_plane)(struct drm_plane *plane,struct drm_crtc *crtc, struct drm_framebuffer *fb,int crtc_x, int crtc_y,unsigned int crtc_w, unsigned int crtc_h,uint32_t src_x, uint32_t src_y,uint32_t src_w, uint32_t src_h,struct drm_modeset_acquire_ctx *ctx);/*DRM_IOCTL_MODE_SETPLANE IOCTL调用时,fb id参数,如果为0,就会调用该接口*关闭plane, atomic modeset使用drm_atomic_helper_disable_plane()实现该hook*/int (*disable_plane)(struct drm_plane *plane,struct drm_modeset_acquire_ctx *ctx);//该接口仅在driver卸载的时候通过drm_mode_config_cleanup()调用来清空plane资源void (*destroy)(struct drm_plane *plane);/*reset plane的软硬件状态, 通过drm_mode_config_reset接口调用*atomic drivers 使用drm_atomic_helper_plane_reset()实现该hook*/void (*reset)(struct drm_plane *plane);/*设置属性的legacy入口, atomic drivers不使用*/int (*set_property)(struct drm_plane *plane,struct drm_property *property, uint64_t val);/*复制plane state, atomic driver必须要有该接口*drm_atomic_get_plane_state会调用到该hook*/struct drm_plane_state *(*atomic_duplicate_state)(struct drm_plane *plane);//销毁plane statevoid (*atomic_destroy_state)(struct drm_plane *plane,struct drm_plane_state *state);/*设置驱动自定义的属性, 通过drm_atomic_plane_set_property调用*/int (*atomic_set_property)(struct drm_plane *plane,struct drm_plane_state *state,struct drm_property *property,uint64_t val);//获取驱动自定义的属性, 通过drm_atomic_plane_get_property调用int (*atomic_get_property)(struct drm_plane *plane,const struct drm_plane_state *state,struct drm_property *property,uint64_t *val);//drm_dev_register接口调用后,调用该hook注册额外的用户接口int (*late_register)(struct drm_plane *plane);//drm_dev_unregister()前调用,unregister用户空间接口void (*early_unregister)(struct drm_plane *plane);//打印plane state, drm_atomic_plane_print_state()会调用void (*atomic_print_state)(struct drm_printer *p,const struct drm_plane_state *state);//检查format和modifier是否有效bool (*format_mod_supported)(struct drm_plane *plane, uint32_t format,uint64_t modifier);
};
常用接口的调用逻辑如下:
(1) update_plane
配置plane的crtc和framebuffer. src_x/src_y/src_w/src_h指定fb的源区域。crtc_x/crtc_y/crtc_w/crtc_h指定其显示在crtc上的目标区域。atomic操作使用drm_atomic_helper_update_plane实现
//用户态
drmModeSetPlaneDRM_IOCTL(fd, DRM_IOCTL_MODE_SETPLANE, ...)
//内核态
DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPLANE, drm_mode_setplane, ...)//drm_mode_setplanesetplane_internalif ( atomic ){__setplane_atomicplane->funcs->update_plane}else{__setplane_internalplane->funcs->update_plane}
(2) disable_plane
DRM_IOCTL_MODE_SETPLANE IOCTL调用时(对应drm_mode_setplane接口),fb id参数,如果为0,就会调用该接口关闭plane, atomic modeset使用drm_atomic_helper_disable_plane()实现该hook, 这里说的disable plane其实就是将plane的参数(crtc/fb/src_x/src_y/等)设置为空
//用户态
drmModeSetPlaneDRM_IOCTL(fd, DRM_IOCTL_MODE_SETPLANE, ...)
//内核态
DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPLANE, drm_mode_setplane, ...)//drm_mode_setplanesetplane_internalif ( atomic ){__setplane_atomic//no fb means shut is downif (!fb) plane->funcs->disable_plane}else{__setplane_internalif (!fb) plane->funcs->disable_plane}
(3)set_property
设置属性的legacy入口, atomic drivers不使用, 用户态通过drmModeObjectSetProperty调用
//用户态
drmModeObjectSetPropertyDRM_IOCTL(fd, DRM_IOCTL_MODE_OBJ_SETPROPERTY, &prop)
//内核态DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_SETPROPERTY, drm_mode_obj_set_property_ioctl, DRM_MASTER)//drm_mode_obj_set_property_iotlset_property_legacyswitch(obj->type){case DRM_MODE_OBJECT_CONNECTOR://设置connector的属性ret = drm_connector_set_obj_prop(obj, prop, prop_value)connector->funcs->set_propertycase DRM_MODE_OBJECT_CRTC://设置crtc的属性ret = drm_mode_crtc_set_obj_propcrtc->funcs->set_propertycase DRM_MODE_OBJECT_PLANE://设置plane的属性ret = drm_mode_plane_set_obj_prop//调用plane的set_property hookret = plane->funcs->set_property(plane, property, value)}
从上边的代码逻辑中也可以看出 conncect/crtc也都有自己的set_property接口
(4)atomic_duplicate_state/atomic_destroy_state
复制/销毁plane 的state, 这两个hook 是atomic driver必须要有的,一般驱动会自定义一个接口并在内部调用__drm_atomic_helper_plane_duplicate_state/__drm_atomic_helper_plane_destroy_state, 例子可以参考vkms_plane_duplicate_state/vkms_plane_destroy_state
(5)atomic_set_property/atomic_get_property
设置/获取驱动私有的属性,这里的私有的属性是指除了drm core框架指定的标准属性外的自定义属性, 私有属性的定义和使用如下:
a) 私有属性创建绑定, 以omap drm为例:
//私有属性创建绑定, 以omap drm为例:
omap_modeset_initomap_modeset_init_propertiesstruct omap_drm_private *priv = dev->dev_private//创建一个zorder_prop属性实例priv->zorder_prop = drm_property_create_range(dev, 0, ...)omap_plane_initomap_plane_install_properties(plane, &plane->base)struct omap_drm_private *priv = dev->dev_private//将zorder_prop实例绑定到plane->base中drm_object_attach_property(obj, priv->zorder_prop, 0);
类似的crtc/connector私有属性也应该是这么创建绑定的
b) 私有属性的获取
用户态通过调用接口drmModeGetPlaneResources获取plane_id后,调用drmModeObjectGetProperties接口,会得到plane_id对应的所有属性,这里边就包括框架提供的(fb/src_x等)以及私有属性。在上文中,我们知道私有属性都绑定在plane->base这个drm_mode_object实例中,其有唯一标识的plane->base.id(即plane_id), 反过来也就可以更加plane_id找到其所有的属性,包括私有属性。
//user
drmModeObjectGetProperties(fd, object_id, object_type)drmIoctl(fd, DRM_IOCTL_MODE_OBJ_GETPROPERTIES, &properties)//kernel
drm_mode_obj_get_properties_ioctl//根据obj_id找到obj对象(如plane->base)drm_mode_object* obj = drm_mode_object_find(arg->obj_id, arg->obj_type)//查找obj中的属性及其属性值drm_mode_object_get_properties(obj, arg->props_ptr, arg->prop_values_ptr, &arg->count_props)__drm_object_property_get_value//获取属性值drm_atomic_get_property(obj, property, val)switch(obj->type){case DRM_MODE_OBJECT_CONNECTOR:drm_atomic_connector_get_propertycase DRM_MODE_OBJECT_CRTC:drm_atomic_crtc_get_propertycase DRM_MODE_OBJECT_PLANE:drm_atomic_plane_get_property(plane, plane->state, property, val)//1.获取标准属性值,如crtc_x/crtc_y/fb_id等//2.获取私有属性plane->funcs->atomic_get_property(plane, state, property,val)}
类似的crtc/connector私有属性也应该是这么获取的
c) 私有属性的设置
和获取的逻辑基本相同。用户态接口是drmModeObjectSetProperty,对应内核态接口为
drm_mode_obj_set_property_ioctl---> set_property_atomic---> drm_atomic_set_property--->
drm_atomic_plane_set_property---> plane->funcs->atomic_set_property
类似的crtc/connector私有属性也应该是这么设置的
四 plane->helper_private
struct drm_plane_helper_funcs {//准备fb,主要包括设置fb fence, 映射fb虚拟地址等int (*prepare_fb)(struct drm_plane *plane,struct drm_plane_state *new_state);//和prepare_fb是相反的操作,比如解除fb虚拟地址的映射void (*cleanup_fb)(struct drm_plane *plane,struct drm_plane_state *old_state);//可选的检查plane属性的约束项int (*atomic_check)(struct drm_plane *plane,struct drm_atomic_state *state);/*更新plane的属性状态到软硬件中, 这个接口才是真正更新参数*/void (*atomic_update)(struct drm_plane *plane,struct drm_atomic_state *state);//disable plane 非必需,不做介绍void (*atomic_disable)(struct drm_plane *plane,struct drm_atomic_state *state);//异步检查 后续了解int (*atomic_async_check)(struct drm_plane *plane,struct drm_atomic_state *state);//异步更新,后续了解void (*atomic_async_update)(struct drm_plane *plane,struct drm_atomic_state *state);
};
(1)prepare_fb
准备fb,主要包括设置fb fence, 映射fb虚拟地址等, 以vkms_prepare_fb为例
vkms_prepare_fb(struct drm_plane *plane,struct drm_plane_state *state)//根据drm_framebuffer实例(state->fb)找到实际的内存对象drm_gem_object * gem_obj//注意这两者之间的关联是通过drmModeAddFB接口,其参数handle(对应drm_gem_object实例),//fb_id对应drm_fframebuffer实例struct drm_gem_object *gem_obj = drm_gem_fb_get_obj(state->fb, 0)//1.映射虚拟地址ret = drm_gem_shmem_vmap(gem_obj, &map); //2.设置fb的fence到state, 这里涉及到dma_fence的同步使用drm_gem_plane_helper_prepare_fb(plane, state)drm_gem_object* obj=drm_gem_fb_get_obj(state->fb, 0)dma_fence* fence = dma_resv_get_excl_rcu(obj->resv)drm_atomic_set_fece_for_plane(state, fence)//设置fb的fence到state,plane_state->fence = fence;
上边准备好dma-fence之后,会在atmic操作中,等待独占dma-fence被signal,如下:
int drm_atomic_helper_wait_for_fences(struct drm_device *dev,struct drm_atomic_state *state,bool pre_swap){for_each_new_plane_in_state(state, plane, new_plane_state, i) {if (!new_plane_state->fence)continue;ret = dma_fence_wait(new_plane_state->fence, pre_swap);if (ret)return ret;dma_fence_put(new_plane_state->fence);new_plane_state->fence = NULL;}return 0;}
dma-fence可以参考文章:
linux GPU上多个buffer间的同步之ww_mutex、dma_fence的使用 笔记 - -Yaong- - 博客园
prepare_fb在drm_atomic_helper_commit中被调用,逻辑如下:
drm_atomic_helper_commitret = drm_atomic_helpr_prepare_planes(dev, state)funcs = plane->helper_private//调用prepare_fb 读取fb的独占dma-fenceret = funcs->prepare_fb(plane, new_plane_state)if (!nonblock)ret = drm_atomic_helper_wait_for_fences(dev, state, true)//等待独占dma-fence被signalret = dma_fence_wait(new_plane_state->fence, pre_swap)
(2)atomic_check
crtc/plane/connector/encoder都有atomic_check接口用来检查其约束项。从下边的逻辑可以看出这些接口都是在atomic modeset时通过drm_atomic_check_only调用的
drm_mode_atomic_ioctldrm_atomic_check_onlyconfig->funcs->atomic_check //drm_mode_config_funcs.atomic_check = drm_atomic_helper_check//调用connector/encoder的atomic_checK接口检查其约束项drm_atomic_helper_check_modesetdrm_atomic_helper_check_planes//调用plane的atomic_check检查约束项funcs = plane->helper_privatefuncs->atomic_check//调用crtc的atomic——check检查约束项funcs = crtc->helper_privatefuncs->atomic_check//提交前也会调用drm_atomic_check_only接口,check失败的话,则不会提交modesetdrm_atomic_commitret = drm_atomic_check_onlyif (ret)return ret;
(3)atomic_update
更新plane的属性状态到软硬件中, 这个接口才是真正更新参数,通过drm_atomic_helper_commit触发调用流程。
以vkms_plane_atomic_update为例:
vkms_plane_atomic_updatecomposer = vkms_plane_state->composer;//将modeset参数更新到composer中,在vkms_composer_worker工作队列中//会调用这些参数进行合成处理memcpy(&composer->src, &new_state->src, sizeof(struct drm_rect));memcpy(&composer->dst, &new_state->dst, sizeof(struct drm_rect));memcpy(&composer->fb, fb, sizeof(struct drm_framebuffer));memcpy(&composer->map, &shadow_plane_state->data, sizeof(composer->map));drm_framebuffer_get(&composer->fb);composer->offset = fb->offsets[0];composer->pitch = fb->pitches[0];composer->cpp = fb->format->cpp[0];
DRM框架(vkms)分析(6)---- plane初始化相关推荐
- DRM框架(vkms)分析(4)----encoder初始化
本文 主要分析encoder的初始化和配置,drm_encoder结构体如下: /*** struct drm_encoder - central DRM encoder structure* @de ...
- DRM框架(vkms)分析(9)----drm驱动创建fbdevice分析(以rockchip_drm_drv为例)
本文主要介绍DRM框架里的fbdev兼容逻辑 一 framebuffer框架简单介绍 framebuffer框架下fbdev的注册主要三步步: (1)创建fbdev操作函数,以rockchip为例: ...
- Linux内核4.14版本——drm框架分析(1)——drm简介
目录 1. DRM简介(Direct Rendering Manager) 1.1 DRM发展历史 1.2 DRM架构对比FB架构优势 1.3 DRM图形显示框架 1.4 DRM图形显示框架涉及元素 ...
- Android DRM框架分析
Android DRM框架分析 1. DRM框架 2.DRM架构 3.DRM插件 4. 实现 5.DRM插件详情 6.MediaDrm 7.MediaCrypto 8.参考链接 1. DRM框架 An ...
- Linux图形显示DRM框架学习
一.Direct Rendering Manager(DRM)是linux内核子系统,负责与显卡交互.DRM提供一组API,用户空间程序可以使用该API将命令和数据发送到GPU或者专用图形处理硬件(如 ...
- uboot drm框架
uboot drm框架 drm概念 drm显示通路 CRTC: 显示控制器, 在 rockchip 平台是 SOC 内部 VOP(部分文档也称为 LCDC)模块的抽象: Plane: 图层, 在 ro ...
- DRM驱动代码分析:图层参数更新
前言: 无业居家,闭门造车.非常欢迎大家帮忙指正. 有些代码流程是看代码分析的,没有去验证是否正确 我对DRM框架的很多东西都不了解,所以有些地方会比较生硬.熟悉学习需要时间,文章一直堆在草稿箱可能会 ...
- DRM驱动代码分析:开机过程中显示驱动做了什么
前言: 有些信息是在网上查资料后总结的,没有去追代码验证.如果有说得不对的地方,欢迎提出指正.感谢! 手机启动的大致流程 1.长按开机键 2.执行存储在ROM里(应该是某一个固定地址或是预定义的地址) ...
- nginx源码分析之模块初始化
在nginx启动过程中,模块的初始化是整个启动过程中的重要部分,而且了解了模块初始化的过程对应后面具体分析各个模块会有事半功倍的效果.在我看来,分析源码来了解模块的初始化是最直接不过的了,所以下面主要 ...
- Android以太网框架情景分析之启动简介
Android以太网框架情景分析之启动简介 Android网络框架分析系列文章目录: Android P适配以太网功能开发指南 Android以太网框架情景分析之启动简介 Androi ...
最新文章
- 软件架构自学笔记----分享“去哪儿 Hadoop 集群 Federation 数据拷贝优化”
- 《Asp.Net 2.0 揭秘》读书笔记(八)
- 零基础python入门书籍推荐书目_铁粉看过来!送书啦,Python推荐书单,送书10本!...
- android studio 7200u,超惊艳的设计!微软正式将Surface Studio和Surface Laptop带进中国:设计师们都看哭了...
- ActiveMQ的介绍及使用实例.
- 如何优雅地本地化构建Mybatis源码
- 【推荐】2017年你应该了解的11款新型编程工具
- python定时发送微信消息_Python3 itchat实现微信定时发送群消息的实例代码
- 并发测试工具_性能测试工具基本工作原理及基本操作流程
- 正则表达式系统教程.CHM
- python往list中添加tuple
- UVA11764 Jumping Mario【Ad Hoc】
- 如何保存ISE综合后的RTL schematic为pdf
- 利用tusharepro进行投资组合优化
- 百度地图API(WEB端/JavaScript API)--实际运用与扩展
- Excel股票分析工具_每日连板清单
- mysql常用的tamper脚本,Sqlmap Tamper绕过脚本详解
- 【MATLAB】图像二值化(imbinarize函数)
- 使用cmake生成ios 的xcode工程,支持Objective-C,c++混合编程
- CPU密集型 vs IO密集型