2021-10-27

Linux图形子系统
参考链接:http://www.wowotech.net/graphic_subsystem/graphic_subsystem_overview.html
GUI:图形子系统的本质,提供图形化的人机交互界面,
在这里插入图片描述

Windowing system(窗口系统):GUI的一种,一般使用client-server架构;server(display server)管理所有的输入设备,以及用于输出的显示设备;应用程序作为server的一个client在自己的窗口运行,绘制自己的GUI;

X window sytem(window system的一种实现):简称X,或者X11,是跨平台的;
硬件加速:通过特定功能的硬件模块,来处理CPU不擅长的事务的方法,称作为硬件加速
在这里插入图片描述

Linux内核DRM和KMS驱动简介
DRM驱动开发
参考:https://blog.csdn.net/hexiaolong2009/article/details/89810355
DRM内部的Objects
在这里插入图片描述
Objects关联关系

创建 crtc/plane/encoder/connector objects,需要调用 drm_xxx_init()。
创建 framebuffer object,需要实现 fb_create() callback。
创建 gem object,需要实现 dumb_create() callback。
创建 property objects,需要调用 drm_mode_config_init()。
让这些 objects 动起来,需要实现各种 funcs 和 helper funcs。
支持 atomic 操作,需要实现 atomic_commit() callback。
MIPI三种接口:DSI、DPI、DBI(不同的接口结构稍有不同)
https://blog.csdn.net/longxiaowu/article/details/24249971
Atomic 操作依赖 VSYNC 中断(即 VBLANK 事件)
dumb buffer 就代表了所有的绘图操作都由 CPU 来完成的 framebuffer。
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 等显示设备的抽象;
参考kirin_970DRM驱动:
驱动编写

kirin_drm_platform_probe函数
1、component_match_add(dev, &match, compare_of, remote); 添加设备组件
2、component_master_add_with_match(dev, &kirin_drm_ops, match);注册超级设备master到component框架中
2.1、调用try_to_bring_up_master函数,尝试初始化该master,设备匹配成功会进行各种设备的回调,从master的bind回调开始,然后调用component_bind_all函数进行各子设备的bind回调。
int kirin_drm_bind(struct device *dev) master设备的绑定函数
1、drm_dev_alloc(driver, dev); 初始化一个新的设备,没有注册
2、kirin_drm_kms_init(drm_dev);kms初始化
2.1、drm_mode_config_init(dev); 初始化DRM模式配置的结构体,初始化一些全局的数据结构
kirin_drm_mode_config_init(dev);初始化不同设备特有的模式配置
2.2、dc_ops->init(dev); 显示控制器初始化
♥2.3、component_bind_all(dev->dev, dev); 绑定和初始化DRM子系统的其他设备驱动
♥2.3.1、component->ops->bind(component->dev, master->dev, data); 调用各个设备的bind函数
以hikey970为例,使用dsi屏幕component_ops dsi_ops–>dsi_bind(struct device *dev, struct device *master,void *data); 在dw_drm-dsi.c
3、dw_drm_encoder_init(dev, drm_dev, &dsi->encoder); 编码器初始化工作
3.1、drm_of_find_possible_crtcs(drm_dev, dev->of_node);找到配的crtc通道encoder->possible_crtcs = crtc_mask;适配对应的编码器和crtc,
3.2、drm_encoder_init(drm_dev, encoder, &dw_encoder_funcs,DRM_MODE_ENCODER_DSI, NULL);编码器初始化
3.3、drm_encoder_helper_add(encoder, &dw_encoder_helper_funcs); 一些编码器的配置函数
4、dsi_bridge_init(drm_dev, dsi); 注册encoder后桥接到转换芯片(有转换芯片的会有桥接);
5、 dsi_connector_init(drm_dev, dsi);- DSI屏幕连接器初始化
5.1、drm_connector_helper_add(connector,&dsi_connector_helper_funcs); 连接器配置函数初始化
5.2、drm_connector_init(dev, &dsi->connector, &dsi_atomic_connector_funcs ,DRM_MODE_CONNECTOR_DSI); 连接器初始化
5.3、drm_mode_connector_attach_encoder(connector, encoder); 连接器和编码器的适配连接;
5.4、drm_panel_attach(dsi->panel, connector);连接器连接显示屏幕 以便获取屏幕参数
6、drm_vblank_init(dev, dev->mode_config.num_crtc); Atomic 操作依赖 VSYNC 中断(即 VBLANK 事件),因此需要使用 hrtimer 来提供软件中断信号。在驱动初始化时调用 drm_vblank_init(),在 VSYNC 中断处理函数中调用 drm_handle_vblank()
7、drm_mode_config_reset(dev); 保存当前各个crtc、connector、encoder状态,方便以后可以恢复
8、kirin_drm_fbdev_init(dev); 初始化fbdev helper函数,ioctl操作执行的功能函数
8.1、drm_fb_helper_prepare(dev, helper, &kirin_fb_helper_funcs);准备fb的操作函数
8.1.1、kirin_fbdev_create(struct drm_fb_helper *helper,struct drm_fb_helper_surface_size *sizes);创建fb
8.1.2、kirin_framebuffer_init(dev, &mode_cmd);根据传入的操作数据,初始化缓冲帧。
8.1.3、kirin_alloc_fb_buffer(fbdev, size);使用ion内存管理机制分配内存,映射到对应的物理地址
8.1.4、drm_fb_helper_alloc_fbi(helper); 创建缓冲区对象
8.2、drm_fb_helper_init(dev, helper,dev->mode_config.num_crtc, dev->mode_config.num_connector);初始化操作函数信息结构体
8.2、drm_helper_disable_unused_functions(dev);在进入KMS模式前禁用所有可能的输出/crtcs
9、drm_kms_helper_poll_init(dev); 初始化kms轮询,控制连接器轮询输出
10、 drm_dev_register(drm_dev, 0); 注册DRM设备
11、kirin_drm_connectors_register(drm_dev); DRM连接器注册函数 (要在DRM设备注册之后)
DMA-buf
解决各个驱动之间buffer共享的问题,不同设备、子系统之间进行共享缓存的统一框架
dma_buf子系统:
dma_ops方法集
DMA提供的硬件访问接口API:
dma_buf_attach(); 用于建立一个dma_buf和device的连接关系,这个连接关系放在新创建dma_buf_attachment对象中,供后续调用dma_buf_map_attachment()使用
Dma_buf_map_attachment(); 生成sg_table和同步cache 必须先调用attach在调用map attachment
Sg_table:本质上是由一块块单个物理连续的buffer所组成的链表,从整体上看是离散的。
在这里插入图片描述
使用for循环解析整个链表,获取对应的buffer的物理地址和长度
ION
https://blog.csdn.net/zhuyong006/article/details/81166618
ION是内存管理器,用来支持不同的内存分配机制。可以被用户空间的进程之间或者内核空间的模块之间进行内存共享
在这里插入图片描述
主要数据结构:
ion_device:一般一个系统只有一个实例
Ion_client:由 ion_client_create() [ion.c] 创建,在ion_device结构体中指定ion_client
Ion_handle:用户空间常用它来表示 buffer,通过 ion_handle_create() [ion.c] 分配、初始化。
Ion_buffer:表示通过 ION 分配的内存
http://www.360doc.com/content/15/0107/23/426085;_439016548.shtml
Component框架
1.保证系统安装了所有的组件。
2.规定了系统各组件初始化的顺序。
主要应用用来构建子系统,比如display-subsystem一个显示子系统,
https://blog.csdn.net/bulinsheng/article/details/108680019
基本概念:Master和component
Master:表示需要构建的系统。,负责管理该超级设备下的普通设备。
Component:用来表示系统组件。
Component_match:用来匹配系统需要的组件,并规定了组件的初始化顺序。
组件系统工作流程:
1、向组件系统注册component,通过component_add()函数实现,每次注册都会遍历一次master列表,尝试绑定到适合的master中,这个过程是通过master扫描component_match,并遍历component_list,找到符合的mach匹配函数
2、构建component_match 在master注册到系统前的构建,通过component_match_add添加compare条目,用于匹配每一个component。
3、向组件系统注册master通过component_master_add_with_match函数实现,会遍历链表,找到对应的match组件进行绑定
4、Bind执行;组件注册,master注册都会执行ops->bind函数
component_master_add_with_match()注册master设备到component框架中‘
component_match_add()解析设备树属性,并添加到match数组中。
try_to_bring_up_master()尝试初始化master
component_add()注册component
DRM设备应用程序开发
在这里插入图片描述

DRM是linux目前主流的图形显示框架;DRM从模块上划分可以分为3部分:libdrm、KMS、GEM;DRM是直接渲染管理器, 是一个内核级的设备驱动,既可以编译到内核也可以作为标准模块进行加载
libdrm:对底层接口的封装,向上提供通用的API接口,主要是对各种IOCTL接口进行封装。
KMS:更新画面和设置i显示参数
更新画面“显示buffer的切换,多图层的合成方式,每个涂层的显示位置
设置显示参数:包括分辨率、刷新率、电源状态等;
GEM:主要负责显示buffer的分配和释放,也是GPU唯一用到DRM的地方
CRTC 对显示buffer进行扫描,并产生时序信号的硬件模块,通常指Display Controller ENCODER 负责将CRTC输出的timing时序转换成外部设备所需要的信号的模块,如HDMI转换器或DSI Controller CONNECTOR 连接物理显示设备的连接器,如HDMI、DisplayPort、DSI总线,通常和Encoder驱动绑定在一起 PLANE 硬件图层,有的Display硬件支持多层合成显示,但所有的Display Controller至少要有1个plane FB Framebuffer,单个图层的显示内容,唯一一个和硬件无关的基本元素 VBLANK 软件和硬件的同步机制,RGB时序中的垂直消影区,软件通常使用硬件VSYNC来实现 property 任何你想设置的参数,都可以做成property,是DRM驱动中最灵活、最方便的Mode setting机制 DUMB 只支持连续物理内存,基于kernel中通用CMA API实现,多用于小分辨率简单场景 PRIME 连续、非连续物理内存都支持,基于DMA-BUF机制,可以实现buffer共享,多用于大内存复杂场景 fence buffer同步机制,基于内核dma_fence机制实现,用于防止显示内容出现异步问题
在这里插入图片描述

DRM应用程序开发步骤:
1、打开DRM设备
通过open函数打开,检查设备是否支持特性
int drmGetCap(int fd, uint64_t capability, uint64_t *value); 文件描述符、DRM_CAP)DUMB_BUFFER,DRM_CAP_ASYNC_PAGE_FLIP, 0表示不支持,1表示支持
2、查找适配的’crtc + encoder + connector’
2.1 获取drm设备的所有资源**drmModeResPtr drmModeGetResources(int fd); ** 返回值:drmModeRes结构体
释放drm设备的资源:drmModeFreeResources(drmModeResPtr ptr); 无返回值
2.2 查找适配的连接器
获取连接器信息 drmModeConnectorPtr drmModeGetConnector(int fd, uint32); 返回值为 drmModeConnector结构体
释放连接器 :drmModeFreeConnector(drmModeConnectorPtr);
2.3 查找编码器 drmModeEnconderPtr drmModeGetEncoder(int fd, uint32 );
释放编码器:drmModeFreeEncoder(drmModeEnconderPtr *ptr);
2.4 查找与编码器适配的crtc encoder->possible & (1 << j);为1就表示适配
2.5 绑定crtc + encoder + connector 到
3、为crtc创建扫描帧缓冲区
申请创建dumb扫描输出缓冲区 int drmioctl(int fd, unsigned long request, void *arg); 发送ioctl,用于实现libdrm中未实现的io操作

3.2 创建帧缓冲区对象 int drmModeAddFB(fb, kms.)

3.3 准备内存映射

映射内存

4、KMS模式设置

5、绘制图像
对bufmap直接写入对应数据
来源:https://blog.csdn.net/hexiaolong2009/article/details/83720940
libdrm库安装
https://blog.csdn.net/weixin_41028621/article/details/110202300
DRM是DRI框架的一个组件,DRI是为操作系统提供高效的视频加速(对3D渲染提供加速效果)
DRI由两部分组成:1、通用的DRM驱动;2、支持特定显卡的驱动
显存:framebuff就是帧缓冲区,简称fb
DRM架构包括DRM core和DRM驱动,DRM驱动包含GEM和KMS
GEM:内核内部管理图形缓冲区,通过GEM,用户空间进程可以创建、处理和销毁GPU中视频内存的内存对象(显存) 用户进程----->GEM--------->显存------->销毁
KMS:在开始使用缓冲帧之前以及当应用程序或用户需要更改时,执行模式设置操作。包括设置屏幕分辨率、颜色深度(一个像素占几位)、刷新频率等,这个操作称之为模式-设置(mode-setting),一般需要访问硬件以及一些寄存器(对寄存器进行操作,配置显示控制器相关的寄存器)
KMS将输出设备建模和管理为一些列的抽象硬件块,分别为:CRTC、Connector(连接器)、Encoders(编码器)、Plane
CRTC:代表显示控制器的扫描引擎,指向帧缓冲区,读取当前扫描缓冲区中的像素数据,并借助PPL电路老生成视频模式定时信号;每个显示设备至少需要一个CRTC.
连接器:显示控制及那个视频信号发送到要显示的位置。连接到输出设备(显示器)的物理链接(VGA、HDMI)
Encoders(编码器):对来自CRTC的视频模式定时信号进行编码,让其符合预期链接器的格式,一个连接器一次只能接受一个编码器的信号
Plane(虚拟屏幕):不是硬件模块,是包含从CRTC扫描引擎中获得的缓冲区的内存对象。

Atomic Mode Setting设计简介

GRUB命令
GNU GRUB(GRand Unified Bootloader简称“GRUB”)是一个来自GNU项目的多操作系统启动程序。GRUB是多启动规范的实现,它允许用户可以在计算机内同时拥有多个操作系统,并在计算机启动时选择希望运行的操作系统。GRUB可用于选择操作系统分区上的不同内核,也可用于向这些内核传递启动参数
https://blog.csdn.net/whatday/article/details/100759678 grub修复

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值