您当前的位置:首页 > 电脑百科 > 程序开发 > 框架

对于 Display 框架,我需要了解 KMS api 吗?| Linux 驱动

时间:2022-11-18 09:58:25  来源:今日头条  作者:老吴嵌入式

缘由

什么是 KMS ?

要了解 KMS,首先要了解 DRM。

DRM 是 Direct Rendering Manager 的缩写,最初只是用来支持 GPU 的,最初它负责:

 

  • Initialize GPU card, load its firmware, etc.
  • Share the GPU command queue between multiple Applications
  • Manage the memory (allocation, access)

 

那时候,Mode-Setting (包括更新画面、配置 display pipeline、screen resolution、color depth、refresh rate等) 是在 Userspace 中实现的,这样做的缺点是:

 

  • Rendering 和 Mode-Setting 会发生竞争;
  • 不统一,缺少抽象,不同的硬件平台各自为营;

 

后来就引入了 Kernel Mode-Setting (KMS),其实就是将 Mode-Setting 的活移回到内核,DRM driver 即负责访问 GPU 也负责访问 Display Engine,且将 KMS 作为 DRM API 的一部分,如下图:


 

目前我们关注最左边的路径就好,不用太关注 GEM、PRIME 等概念。

图形应用是如何进行显示的?

通常,一个普通的图形应用并不会直接通过 KMS 和内核进行交互,而是先和 display server (例如给予 X11 的 Xorg, 或者基于 Wayland 的 Weston,也称 display compositor) 进行交互:将显示的图像提交给 display server, 再由 display server 负责将多个 client 图形应用的图像合成成一张图像,并将这张图像通过 KMS 的接口提交给内核。

简而言之,就是 2 个步骤:

step1: 合成


 

step2: 提交给内核


 


何时要用 KMS ?

对于普通的图形应用,一般是不会直接去使用 KMS 的。

只有一些需要 low level control 的应用需要使用 KMS,例如:

 

  • Display servers;
  • Media players,例如 Kodi,它们有自己的 KMS backend,不需要额外的 display server;
  • 游戏相关的应用,例如 RetroArch,为了支持更多的平台,它们会做到不依赖 display server;
  • VR、XR,它们对性能要求很严格,所以会亲自访问 KMS 以达到最小的延迟;

 

既然很少直接使用 KMS,为什么还要学习它 ?

 

  • DRM Driver 的驱动开发人员有必要了解 KMS api,这样才能理解 DRM Driver 的设计目的,从而编写出正确的驱动程序;
  • 理解原理,可以协助我们定位图形应用不稳定或者性能相关的问题,尤其是嵌入式 linux 领域,显示相关的功能复杂且容易出现异常;
  • 如果你想要为开源软件 Wayland 或者 Kodi 做贡献的话,则需要了解 KMS api;
  • 如果你的应用对性能和延迟性要求很高的话,也需要了解 KMS api。

     

     

如何编写 KMS Demo?

 

要编写 KMS 程序,首先要了解 KMS 的模型。

KMS 将硬件模块抽象成下面几个对象类型:

 

  • Planes:图层,例如在 rockchip 平台里对应 SOC 内部 VOP 模块的 win 图层;
  • CRTC:显示控制器,例如在 rockchip 平台里对应 SOC 内部的 VOP 模块;
  • Encoder:输出转换器,指 RGB、LVDS、DSI、eDP、HDMI、CVBS、VGA 等显示接口;
  • Connector:连接器,指 encoder 和 panel 之间交互的接口部分;
  • Bridge:桥接设备,一般用于注册 encoder 后面另外再接的转换芯片,如 DSI2HDMI 转换芯片;
  • Panel:泛指屏,各种 LCD、HDMI 等显示设备的抽象;

 

应用通过 KMS api 将这些对象连接成一条 display pipeline,最终将图像显示在屏幕上:


 

KMS 有两套 api: legacy api (已过时) 和 atomic api:

legacy api 虽说已经过时了,但是它其实是很适合 KMS api 初学者的,因为它仍然是基于 plane、crct、encoder、connector 这些核心概念的。atomic api 只是在 legacy api 基础上进行一些改进,待会会细说。

KMS legacy api 最简单示例:

int main(int argc, char **argv) { int fd; drmModeConnector *conn; drmModeRes *res; uint32_t conn_id; uint32_t crtc_id; /* open the drm device */ fd = open("/dev/dri/card0"); /* get crtc/encoder/connector id */ res = drmModeGetResources(fd); crtc_id = res->crtcs[0]; conn_id = res->connectors[0]; /* get connector for display mode */ conn = drmModeGetConnector(fd, conn_id); /* create a dumb-buffer */ drmIoctl(DRM_IOCTL_MODE_CREATE_DUMB); /* bind the dumb-buffer to an FB object */ drmModeAddFB(...); /* map the dumb buffer for userspace drawing */ drmIoctl(DRM_IOCTL_MODE_MAP_DUMB); mmap(...); /* start display */ drmModeSetCrtc(crtc_id, fb_id, connector_id, mode); }


大致的思路是:

 

  1. 通过 drmModeGetResources() 获取到 crtc、connector 等对象的 id,然后通过 id 获取到具体的 object;
  2. 通过 ioctl(DRM_IOCTL_MODE_CREATE_DUMB) 和 drmModeAddFB() 创建 DRM framebuffer object,并获得 fb id;
  3. 通过 ioctl(DRM_IOCTL_MODE_MAP_DUMB) 和 mmap() 将 framebuffer 映射到用户空间,应用将自己要显示的内容写到 framebuffer 中;
  4. 将 crtc、connector、fb 的id 通过 drmModeSetCrtc() 告诉 DRM driver,让内核帮我们配置好 display pipeline,从而将 framebuffer 里的内容显示出来;

 

嵌入式物联网需要学的东西真的非常多,千万不要学错了路线和内容,导致工资要不上去!

无偿分享大家一个资料包,差不多150多G。里面学习内容、面经、项目都比较新也比较全!某鱼上买估计至少要好几十。

点击这里找小助理0元领取:加微信领取资料


 


 



关于 KMS atomic api:

atomic 的核心思想是将各种设置都保存在一个个的 property 里,最后将所有 property 一次性提交给内核,对于本次 commit 操作,要么成功,要么保持原来的状态完全不变。atomic 的好处在于可以避免操作到一半时中途失败后难以回滚的问题,同时也能避免设置期间屏幕闪烁的问题。


 

non atomic


 

atomic

下面的代码同样也是将 crtc、connector 等对象连成一条 display pipeline,只不过这次用的是 atomic api。

req = drmModeAtomicAlloc(); drmModeAtomicAddProperty(req, crtc_id, property_active, 1); drmModeAtomicAddProperty(req, crtc_id, property_mode_id, blob_id); drmModeAtomicAddProperty(req, conn_id, property_crtc_id, crtc_id); drmModeAtomicCommit(fd, req, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL); drmModeAtomicFree(req);

代码虽然增多了,但是能得到更好的用户体验。

KMS 功能比较多,api 也比较多,需要一系列的文章才能描述清楚,网上已经有一个比较好的教程,我就不再详细描述了。

请参考何小龙的 blog:

 

https://blog.csdn.NET/hexiaolong2009/article/details/83720940

 

相关文章列表:

最简单的DRM应用程序 (single-buffer) 最简单的DRM应用程序 (double-buffer) 最简单的DRM应用程序 (page-flip) 最简单的DRM应用程序 (plane-test) DRM应用程序进阶 (Property) DRM应用程序进阶 (atomic-crtc) DRM应用程序进阶 (atomic-plane)其他适合学习 KMS 的开源软件1. drminfo

https://github.com/ascent12/drm_info

 

drminfo 是一个命令行工具,它可以将系统里 DRM 设备的所有信息都 dump 出来,很适合用于调试。

编译:

$ apt-get install meson ninja-build $ git clone https://github.com/ascent12/drm_info drm_info $ cd drm_info $ meson build/ $ ninja -C build install

用法:

# ./drm_info Node: /dev/dri/card0 ├───Driver: rockchip (RockChip Soc DRM) version 2.0.0 (20140818) │ ├───DRM_CLIENT_CAP_STEREO_3D supported │ ├───DRM_CLIENT_CAP_UNIVERSAL_PLANES supported │ ├───DRM_CLIENT_CAP_ATOMIC supported │ ├───DRM_CLIENT_CAP_ASPECT_RATIO supported │ ├───DRM_CLIENT_CAP_WRITEBACK_CONNECTORS supported │ ├───DRM_CAP_DUMB_BUFFER = 1 │ ├───DRM_CAP_VBLANK_HIGH_CRTC = 1 │ ├───DRM_CAP_DUMB_PREFERRED_DEPTH = 0 │ ├───DRM_CAP_DUMB_PREFER_SHADOW = 0 │ ├───DRM_CAP_PRIME = 3 │ ├───DRM_CAP_TIMESTAMP_MONOTONIC = 1 │ ├───DRM_CAP_ASYNC_PAGE_FLIP = 1 │ ├───DRM_CAP_Cursor_WIDTH = 64 │ ├───DRM_CAP_CURSOR_HEIGHT = 64 │ ├───DRM_CAP_ADDFB2_MODIFIERS = 1 │ ├───DRM_CAP_PAGE_FLIP_TARGET = 0 │ ├───DRM_CAP_CRTC_IN_VBLANK_EVENT = 1 │ ├───DRM_CAP_SYNCOBJ = 0 │ └───DRM_CAP_SYNCOBJ_TIMELINE not supported ├───Device: platform rockchip,display-subsystem │ └───Available nodes: primary, render ├───Framebuffer size │ ├───Width: [0, 8192] │ └───Height: [0, 8192] ├───Connectors │ ├───Connector 0 │ │ ├───Object ID: 77 │ │ ├───Type: eDP │ │ ├───Status: connected │ │ ├───Physical size: 256x144 mm │ │ ├───Subpixel: unknown │ │ ├───Encoders: {0} │ │ ├───Modes │ │ │ └───1920x1080@60.00 nhsync nvsync │ │ └───Properties │ │ ├───"EDID" (immutable): blob = 0 │ │ ├───"DPMS": enum {On, Standby, Suspend, Off} = On │ │ ├───"link-status": enum {Good, Bad} = Good │ │ ├───"non-desktop" (immutable): range [0, 1] = 0 │ │ ├───"CRTC_ID" (atomic): object CRTC = 54 │ │ ├───"brightness": range [0, 100] = 50 │ │ ├───"contrast": range [0, 100] = 50 │ │ ├───"saturation": range [0, 100] = 50 │ │ └───"hue": range [0, 100] = 50 [...] ├───Encoders │ ├───Encoder 0 │ │ ├───Object ID: 76 │ │ ├───Type: TMDS │ │ ├───CRTCS: {0} │ │ └───Clones: {} │ ├───Encoder 1 │ │ ├───Object ID: 78 │ │ ├───Type: TMDS │ │ ├───CRTCS: {0, 1} │ │ └───Clones: {} │ └───Encoder 2 │ ├───Object ID: 80 │ ├───Type: TMDS │ ├───CRTCS: {1} │ └───Clones: {} ├───CRTCs │ ├───CRTC 0 │ │ ├───Object ID: 54 │ │ ├───Mode: 1920x1080@60.00 nhsync nvsync │ │ ├───Gamma size: 256 │ │ └───Properties │ │ ├───"ACTIVE" (atomic): range [0, 1] = 1 │ │ ├───"MODE_ID" (atomic): blob = 91 │ │ │ └───1920x1080@60.00 nhsync nvsync │ │ ├───"OUT_FENCE_PTR" (atomic): range [0, UINT64_MAX] = 0 │ │ ├───"left margin": range [0, 100] = 100 │ │ ├───"right margin": range [0, 100] = 100 │ │ ├───"top margin": range [0, 100] = 100 │ │ ├───"bottom margin": range [0, 100] = 100 │ │ ├───"ALPHA_SCALE" (atomic): range [0, 1] = 1 │ │ └───"FEATURE" (immutable): bitmask {afbdc} = () [...] └───Planes ├───Plane 0 │ ├───Object ID: 53 │ ├───CRTCs: {0} │ ├───FB ID: 128 │ │ ├───Object ID: 128 │ │ ├───Size: 1920x1080 │ │ ├───Pitch: 7680 bytes │ │ ├───Bits per pixel: 32 │ │ └───Depth: 24 │ ├───Formats: │ │ ├───XRGB8888 (0x34325258) │ │ ├───ARGB8888 (0x34325241) │ │ ├───XBGR8888 (0x34324258) │ │ ├───ABGR8888 (0x34324241) │ │ ├───RGB888 (0x34324752) │ │ ├───BGR888 (0x34324742) │ │ ├───RGB565 (0x36314752) │ │ └───BGR565 (0x36314742) │ └───Properties │ ├───"type" (immutable): enum {Overlay, Primary, Cursor} = Primary │ ├───"FB_ID" (atomic): object framebuffer = 128 │ │ ├───Object ID: 128 │ │ ├───Size: 1920x1080 │ │ ├───Pitch: 7680 bytes │ │ ├───Bits per pixel: 32 │ │ └───Depth: 24 │ ├───"IN_FENCE_FD" (atomic): srange [-1, INT32_MAX] = -1 │ ├───"CRTC_ID" (atomic): object CRTC = 54 │ ├───"CRTC_X" (atomic): srange [INT32_MIN, INT32_MAX] = 0 │ ├───"CRTC_Y" (atomic): srange [INT32_MIN, INT32_MAX] = 0 │ ├───"CRTC_W" (atomic): range [0, INT32_MAX] = 1920 │ ├───"CRTC_H" (atomic): range [0, INT32_MAX] = 1080 │ ├───"SRC_X" (atomic): range [0, UINT32_MAX] = 0 │ ├───"SRC_Y" (atomic): range [0, UINT32_MAX] = 0 │ ├───"SRC_W" (atomic): range [0, UINT32_MAX] = 1920 │ ├───"SRC_H" (atomic): range [0, UINT32_MAX] = 1080 │ ├───"ZPOS" (atomic): range [0, 3] = 0 │ ├───"FEATURE" (immutable): bitmask {scale, alpha, hdr2sdr, sdr2hdr, afbdc} = (alpha | afbdc) │ ├───"EOTF" (atomic): range [0, 5] = 0 │ ├───"COLOR_SPACE" (atomic): range [0, 12] = 0 │ ├───"GLOBAL_ALPHA" (atomic): range [0, UINT8_MAX] = 255 │ ├───"BLEND_MODE" (atomic): range [0, 1] = 0 │ ├───"ASYNC_COMMIT" (atomic): range [0, 1] = 0 │ └───"SHARE_ID" (atomic): range [0, UINT32_MAX] = 53 [...]2、libdrm 自带的测试程序:modetest

https://gitlab.freedesktop.org/mesa/drm

 

modetest 是由 libdrm 提供的测试程序,可以查询显示设备的支持状况,进行基本的显示测试,以及设置显示的模式。

编译:

$ apt-get install meson ninja-build $ git clone https://gitlab.freedesktop.org/mesa/drm libdrm $ cd libdrm $ meson build/ $ ninja -C build install

会生成库文件和测试程序:

libkms tests/ # 包含 modetest libdrm.so.2.4.0 libdrm.so.2 libdrm.so

用法:

// 在 edp 屏上显示测试画面 $ modetest -M rockchip -s 77@54:1920x1080 setting mode 1920x1080-60.00Hz on connectors 77, crtc 54 // 在 hdmi 屏上显示测试画面 $ modetest -M rockchip -s 81@65:1920x1080 setting mode 1920x1080-60.00Hz on connectors 81, crtc 65

参数说明:

 

  • -M:用于指定访问哪个 DRM 设备;
  • -s [,][@]:[#][-][@]:用于在指定的 pipeline 上以某个 mode 显示某个 pattern 的画面。
3、kmscube
https://gitlab.freedesktop.org/mesa/kmscube/

 

kmscube 是一个演示程序,用于说明如何在没有 X11、wayland 等 compositor 的情况下编写 bare metal 图形应用。它使用了 DRM/KMS(kernel mode setting)、GBM(graphics buffer manager)和 EGL 来使用 OpenGL 或 OpenGL ES 渲染内容。

编译:

$ apt-get install meson ninja-build $ git clone https://gitlab.freedesktop.org/mesa/kmscube/ kmscube $ cd kmscube $ meson build/ $ ninja -C build install

用法:

$ ./kmscube


 

kmscube 运行效果

还有很多优秀的开源软件,例如 Wayland 的参考实现 Weston,媒体播放器 Kodi、复古游戏模拟器前端 RetroArch 等,都是我们学习 KMS api 的优秀学习资料,感兴趣的小伙伴可以自行研究一波。

到此,KMS api 的基础知识就介绍完毕了,感谢阅读!

文章链接:
https://mp.weixin.qq.com/s/2Wermbnh4GKEF8RvbdDj4A

转载自:老吴嵌入式 ,作者吴伟东Jack

文章链接:对于 Display 框架,我需要了解 KMS api 吗? | Linux 驱动



Tags:Display框架   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
缘由什么是 KMS ?要了解 KMS,首先要了解 DRM。DRM 是 Direct Rendering Manager 的缩写,最初只是用来支持 GPU 的,最初它负责: Initialize GPU card, load its firmware, etc. ...【详细内容】
2022-11-18  Tags: Display框架  点击:(0)  评论:(0)  加入收藏
▌简易百科推荐
缘由什么是 KMS ?要了解 KMS,首先要了解 DRM。DRM 是 Direct Rendering Manager 的缩写,最初只是用来支持 GPU 的,最初它负责: Initialize GPU card, load its firmware, etc. ...【详细内容】
2022-11-18  老吴嵌入式   今日头条  Tags:Display框架   点击:(0)  评论:(0)  加入收藏
前言准确点说,这不是《从零打造项目》系列的第一篇文章,模版代码生成的那个项目讲解算是第一篇,当时就打算做一套项目脚手架,为后续进行项目练习做准备。因时间及个人经验问题...【详细内容】
2022-11-18  Java热点  今日头条  Tags:SpringBoot   点击:(2)  评论:(0)  加入收藏
作者 | 褚杏娟近日,GitHub 前 CTO Jason Warner 在推特上表示,“我确信过去十年中,最大的架构错误之一就是全面使用微服务。”从单体应用到微服务的规划顺序,Warner 的建议是:单...【详细内容】
2022-11-18  InfoQ  今日头条  Tags:GitHub   点击:(3)  评论:(0)  加入收藏
一、Scrapy框架简介Scrapy是:由Python语言开发的一个快速、高层次的屏幕抓取和web抓取框架,用于抓取web站点并从页面中提取结构化的数据,只需要实现少量的代码,就能够快速的抓...【详细内容】
2022-11-16  运维笔记ywbj  今日头条  Tags:Scrapy   点击:(4)  评论:(0)  加入收藏
这里首先需要说明的就是为什么要进行配置文件加密。在当今这个移动互联网横行的时代里,无论是企业的隐私还是个人的隐私都是需要得到保护的。所以我们在实际的操作中会采用...【详细内容】
2022-11-14  架构师面试宝典  今日头条  Tags:Spring Boot   点击:(12)  评论:(0)  加入收藏
深度自定义mybatis回顾mybatis的操作的核心步骤 编写核心类SqlSessionFacotryBuild进行解析配置文件 深度分析解析SqlSessionFacotryBuild干的核心工作 编写核心类SqlSessio...【详细内容】
2022-11-13    网易号  Tags:mybatis   点击:(6)  评论:(0)  加入收藏
WebRTC(Web Real-Time Communication)是为了让开发者在浏览器实现多媒体交换的技术,于2011年被加入W3C规范。当前的支持情况可以见下图。 WebRTC的核心在于建立PeerConnection...【详细内容】
2022-11-11  效能IT哥  今日头条  Tags:WEBRtc   点击:(16)  评论:(0)  加入收藏
由于hystrix官方已经停止维护了,目前spring-cloud推荐使用resilience4j来代替hystrix实现熔断、限流。熔断一般指客户端调用服务端接口出现异常时客户端侧的处理,当然也可以是...【详细内容】
2022-11-10  vivi2020一  今日头条  Tags:spring   点击:(27)  评论:(0)  加入收藏
Spring MVC 的请求处理流程 DispatcherServletDispatcherServlet继承结构 DispatcherServlet对请求的处理流程大致步骤 绑定⼀些 Attribute WebApplicationContext / Loc...【详细内容】
2022-11-08  刷刷的破壳日记  今日头条  Tags:Spring MVC   点击:(14)  评论:(0)  加入收藏
前几天发布了一篇java压缩文件的文章,今天有朋友跟我说,这压缩没啥技术含量啊,你再弄个压缩完然后返回前端下载的功能呗。其实吧我觉得下载功能比压缩更简单吧,压缩的递归我至少...【详细内容】
2022-11-07  天子小门生    Tags:SpringBoot   点击:(27)  评论:(0)  加入收藏
相关文章
    无相关信息
站内最新
站内热门
站内头条