DRM的GEM_drm gem-程序员宅基地

技术标签: linux显示相关  DRM  GEM  

GEM(Graphics Execution Manager)主要完成:内存申请释放、指令执行、执行命令时的光圈管理(what?!)。缓存对象的申请主要与linux提供的shmem层相关。设备相关操作如指令执行、pinning、buffer读写、映射、域所有权的转移等,还是归设备驱动的ioctl。

初始化

使用GEM的驱动必须在struct drm_driver->driver_features置DRIVER_GEM位,DRM core将会在执行load操作前自动初始化GEM core,这就意味着会构建一个DRM内存管理器,这个DRM内存管理器为对象的申请提供地址空间池。

在KMS设置上,如果硬件需要的话,驱动在核心GEM初始化后,需要申请并初始化环形缓冲区,这部分一般不由GEM管理,而是需要独立的初始化到自己的DRM MM对象。

创建GEM对象

GEM将创建GEM对象和其后的申请内存操作分成了两个不同的操作。GEM对象由struct drm_gem_object表示。驱动一般需要用私有信息来扩展GEM对象,因此struct drm_gem_object都是嵌入在驱动私有GEM结构体内的。创建一个GEM对象,驱动为自有GEM对象申请内存,并通过drm_gem_object_init(struct drm_device* ,struct drm_gem_object *,size_t )来初始化嵌入在其中的struct drm_gem_object。

GEM使用shmem来申请匿名页内存,drm_gem_object_init将会根据传入的size_t创建一个shmfs,并将这个shmfs file放到struct drm_gem_object的filp区。当图形硬件使用系统内存,这些内存就会作为对象的主存储直接使用,否则就会作为后备内存。驱动负责调用shmem_read_mapping_page_gfp()做实际物理页面的申请,初始化GEM对象时驱动可以决定申请页面,或者延迟到需要内存时再申请(需要内存时是指:用户态访问内存发生缺页中断,或是驱动需要启动DMA用到这段内存)。

匿名页面内存并不是一定需要的,嵌入式设备一般需要物理连续系统内存,驱动可以创建GEM对象儿没有shmfs,并调用drm_gem_private_object_init()初始化此私有GEM对象,不过这样的话,私有GEM对象的存储管理就需要驱动自行完成。

GEM对象的生命周期

所有GEM对象都有GEM core做引用计数,drm_gem_object_get()加数,drm_gem_object_put()减数,执行drm_gem_object_get()调用者必须持有struct drm_device的struct_mutex锁,而为了方便也提供了drm_gem_object_put_unlocked()也可以不持锁操作。当最后一个对GEM对象的引用释放时,GEM core调用struct drm_driver gem_free_object_unlocked,这一操作对于使能了GEM的驱动来说是必须,并且必须释放所有相关资源。driver实现接口void (*gem_free_object)(struct drm_gem_object *obj),负责释放所有GEM对象资源,这其中包括要调用drm_gem_object_release()来释放GEM core创建的资源。

GEM对象命名

GEM对象有本地handle、全局名称和文件描述符,都是32bit数。

对于本地handle:drm_gem_handle_create()创建GEM对象handle,这个函数拿着DRM file的指针和GEM对象,算得一个局部唯一handle,这个handle可以通过drm_gem_handle_delete()来删除,drm_gem_object_lookup()可以由handle找出对应的GEM对象。handle仅是一个对GEM对象的引用,在handle销毁时减去这一引用。

对于全局名称:可以在进程之间传递,不过在DRM API中,全局名称不能直接指到GEM对象,通过ioctl的DRM_IOCTL_GEM_FLINK (转成对象)和DRM_IOCTL_GEM_OPEN(转回全局名称),DRM core做此转换。GEM也支持通过PRIME dma-buf文件描述符的缓存共享,基于GEM的驱动必须使用提供的辅助函数来实现exoprting和importing。共享文件描述符比可以被猜测的全局名称更安全,因此是首选的缓存共享机制。通过GEM全局名称进行缓存共享仅在传统用户态支持。更进一步的说,PRIME由于其基于dma-buf,还允许跨设备缓存共享。

GEM对象映射

因为映射操作费时,GEM更多使用ioctl将内存映射到用户态,通过读写访问缓存;但是当随机访问缓存多的时候,如使用了软渲染,直接访问GEM对象高效。mmap系统调用不能直接映射GEM对象,因为GEM对象没有自己的文件描述符。目前同时存在两种map GEM对象到用户态的办法,一是用驱动自己的ioctl做映射操作,钩子后面挂上do_mmap(),不鼓励,比描述了;另一种方法是对DRM文件描述符使用mmap直接映射GEM对象,虽然GEM对象没有文件描述符,但是通过mmap(void*addr,size_t length,int port,int flags,int fd, off_t offset)中的offset参数,DRM可以找出这个GEM对象,为了能识别这个offset,驱动必须先对这个GEM对象执行了drm_gem_create_mmap_offset(),这样得到的offset值需要先通过驱动指定的方式传给用户态程序,然后就可以通过mmap传下来,找到这个GEM对象。GEM core提供有一个辅助方法drm_gem_mmap()来处理对象映射,这个方法可以直接设置为mmap文件操作的处理函数,它将会由offset查出GEM对象,然后设置VMA操作到struct drm_driver的gem_vm_ops;注意drm_gem_mmap()不映射内存到用户态,需要依赖于驱动提供的缺页处理函数做页面的映射,因此要用drm_gem_mmap(),驱动必须将struct drm_driver的gem_vm_ops填入,也就是填好

struct vm_operations_struct{

    void (*open)(struct vm_area_struct* area);

    void (*close)(struct vm_area_struct* area);

    vm_fault_t (*fault)(struct vm_fault* vamp);

}

其中,open/close需要更新GEM对象的引用计数,驱动可以用drm_gem_vm_open()和drm_gem_vm_close()辅助函数直接作为open/close的处理函数;fault操作的处理函数负责在缺页发生时映射独立页面到用户态,驱动可以根据内存申请方案在缺页发生时申请页面,也可以在GEM对象建立时申请。对于没有MMU的平台,还有其他考虑,但是不予介绍。

内存对齐

当一个对象的后备页面映射到设备或用于指令缓存,这个页面就会被刷到内存并标记为CPU与GPU都会写入,比如:GPU渲染到一个对象,渲染完后CPU访问这个对象,那么这个对象就必须与CPU的内存视图保持一致,这就需要通过调用GPU缓存外刷等操作。这种CPU-GPU内存对齐的管理就由驱动指定的ioctl提供:看看对象当前域,必要的话要做刷新或同步使对象转到想要的域,不过对象可能会忙(比如正在被渲染),这时候就会发生阻塞,等待渲染完成,再做刷新或同步。

指令执行

提供指令执行接口给client可能是GEM最重要的功能,client程序构建指令缓存并提交到GEM,而这个指令缓存会引用到很多已经申请过的内存对象;这时候,GEM小心翼翼的绑定所有的对象到GTT,执行这个指令缓存,然后在client们之间提供必要的同步。这个过程中一般还会有扔掉一些对象,以及再绑进一些对象(开销很大),然后还要提供重映射将GTT的偏移量对client们隐藏起来。client们也要注意提交的指令缓存所引用的内存对象不要超过GTT的要求,如果超过则会被GEM拒绝,然后就不会有渲染操作执行了。一般来说,如果指令缓存中的这段渲染操作中的很多对象都需要申请fence寄存器,那么就要注意不要超过可以提供给client使用的fence寄存器的总数。这些资源的管理都要从libdrm重的客户端中抽象出来。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/ytfy339784578/article/details/104557569

智能推荐

c# 调用c++ lib静态库_c#调用lib-程序员宅基地

文章浏览阅读2w次,点赞7次,收藏51次。四个步骤1.创建C++ Win32项目动态库dll 2.在Win32项目动态库中添加 外部依赖项 lib头文件和lib库3.导出C接口4.c#调用c++动态库开始你的表演...①创建一个空白的解决方案,在解决方案中添加 Visual C++ , Win32 项目空白解决方案的创建:添加Visual C++ , Win32 项目这......_c#调用lib

deepin/ubuntu安装苹方字体-程序员宅基地

文章浏览阅读4.6k次。苹方字体是苹果系统上的黑体,挺好看的。注重颜值的网站都会使用,例如知乎:font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, PingFang SC, Microsoft YaHei, Source Han Sans SC, Noto Sans CJK SC, W..._ubuntu pingfang

html表单常见操作汇总_html表单的处理程序有那些-程序员宅基地

文章浏览阅读159次。表单表单概述表单标签表单域按钮控件demo表单标签表单标签基本语法结构<form action="处理数据程序的url地址“ method=”get|post“ name="表单名称”></form><!--action,当提交表单时,向何处发送表单中的数据,地址可以是相对地址也可以是绝对地址--><!--method将表单中的数据传送给服务器处理,get方式直接显示在url地址中,数据可以被缓存,且长度有限制;而post方式数据隐藏传输,_html表单的处理程序有那些

PHP设置谷歌验证器(Google Authenticator)实现操作二步验证_php otp 验证器-程序员宅基地

文章浏览阅读1.2k次。使用说明:开启Google的登陆二步验证(即Google Authenticator服务)后用户登陆时需要输入额外由手机客户端生成的一次性密码。实现Google Authenticator功能需要服务器端和客户端的支持。服务器端负责密钥的生成、验证一次性密码是否正确。客户端记录密钥后生成一次性密码。下载谷歌验证类库文件放到项目合适位置(我这边放在项目Vender下面)https://github.com/PHPGangsta/GoogleAuthenticatorPHP代码示例://引入谷_php otp 验证器

【Python】matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距-程序员宅基地

文章浏览阅读4.3k次,点赞5次,收藏11次。matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距

docker — 容器存储_docker 保存容器-程序员宅基地

文章浏览阅读2.2k次。①Storage driver 处理各镜像层及容器层的处理细节,实现了多层数据的堆叠,为用户 提供了多层数据合并后的统一视图②所有 Storage driver 都使用可堆叠图像层和写时复制(CoW)策略③docker info 命令可查看当系统上的 storage driver主要用于测试目的,不建议用于生成环境。_docker 保存容器

随便推点

网络拓扑结构_网络拓扑csdn-程序员宅基地

文章浏览阅读834次,点赞27次,收藏13次。网络拓扑结构是指计算机网络中各组件(如计算机、服务器、打印机、路由器、交换机等设备)及其连接线路在物理布局或逻辑构型上的排列形式。这种布局不仅描述了设备间的实际物理连接方式,也决定了数据在网络中流动的路径和方式。不同的网络拓扑结构影响着网络的性能、可靠性、可扩展性及管理维护的难易程度。_网络拓扑csdn

JS重写Date函数,兼容IOS系统_date.prototype 将所有 ios-程序员宅基地

文章浏览阅读1.8k次,点赞5次,收藏8次。IOS系统Date的坑要创建一个指定时间的new Date对象时,通常的做法是:new Date("2020-09-21 11:11:00")这行代码在 PC 端和安卓端都是正常的,而在 iOS 端则会提示 Invalid Date 无效日期。在IOS年月日中间的横岗许换成斜杠,也就是new Date("2020/09/21 11:11:00")通常为了兼容IOS的这个坑,需要做一些额外的特殊处理,笔者在开发的时候经常会忘了兼容IOS系统。所以就想试着重写Date函数,一劳永逸,避免每次ne_date.prototype 将所有 ios

如何将EXCEL表导入plsql数据库中-程序员宅基地

文章浏览阅读5.3k次。方法一:用PLSQL Developer工具。 1 在PLSQL Developer的sql window里输入select * from test for update; 2 按F8执行 3 打开锁, 再按一下加号. 鼠标点到第一列的列头,使全列成选中状态,然后粘贴,最后commit提交即可。(前提..._excel导入pl/sql

Git常用命令速查手册-程序员宅基地

文章浏览阅读83次。Git常用命令速查手册1、初始化仓库git init2、将文件添加到仓库git add 文件名 # 将工作区的某个文件添加到暂存区 git add -u # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,不处理untracked的文件git add -A # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,包括untracked的文件...

分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120-程序员宅基地

文章浏览阅读202次。分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120

【C++缺省函数】 空类默认产生的6个类成员函数_空类默认产生哪些类成员函数-程序员宅基地

文章浏览阅读1.8k次。版权声明:转载请注明出处 http://blog.csdn.net/irean_lau。目录(?)[+]1、缺省构造函数。2、缺省拷贝构造函数。3、 缺省析构函数。4、缺省赋值运算符。5、缺省取址运算符。6、 缺省取址运算符 const。[cpp] view plain copy_空类默认产生哪些类成员函数

推荐文章

热门文章

相关标签