libdrm全解析二十三 —— 源码全解析(20)

news2024/9/28 3:28:14

接前一篇文章:libdrm全解析二十二 —— 源码全解析(19)

本文参考以下博文:

DRM 驱动程序开发(VKMS)

特此致谢!

前一篇文章已提到,drmModeGetResources函数值得深入地进行讲解。本回就来深入讲解一下这个函数。为了便于理解,再次贴出函数代码,如下:

drm_public drmModeResPtr drmModeGetResources(int fd)
{
	struct drm_mode_card_res res, counts;
	drmModeResPtr r = 0;
 
retry:
	memclear(res);
	if (drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res))
		return 0;
 
	counts = res;
 
	if (res.count_fbs) {
		res.fb_id_ptr = VOID2U64(drmMalloc(res.count_fbs*sizeof(uint32_t)));
		if (!res.fb_id_ptr)
			goto err_allocs;
	}
	if (res.count_crtcs) {
		res.crtc_id_ptr = VOID2U64(drmMalloc(res.count_crtcs*sizeof(uint32_t)));
		if (!res.crtc_id_ptr)
			goto err_allocs;
	}
	if (res.count_connectors) {
		res.connector_id_ptr = VOID2U64(drmMalloc(res.count_connectors*sizeof(uint32_t)));
		if (!res.connector_id_ptr)
			goto err_allocs;
	}
	if (res.count_encoders) {
		res.encoder_id_ptr = VOID2U64(drmMalloc(res.count_encoders*sizeof(uint32_t)));
		if (!res.encoder_id_ptr)
			goto err_allocs;
	}
 
	if (drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res))
		goto err_allocs;
 
	/* The number of available connectors and etc may have changed with a
	 * hotplug event in between the ioctls, in which case the field is
	 * silently ignored by the kernel.
	 */
	if (counts.count_fbs < res.count_fbs ||
	    counts.count_crtcs < res.count_crtcs ||
	    counts.count_connectors < res.count_connectors ||
	    counts.count_encoders < res.count_encoders)
	{
		drmFree(U642VOID(res.fb_id_ptr));
		drmFree(U642VOID(res.crtc_id_ptr));
		drmFree(U642VOID(res.connector_id_ptr));
		drmFree(U642VOID(res.encoder_id_ptr));
 
		goto retry;
	}
 
	/*
	 * return
	 */
	if (!(r = drmMalloc(sizeof(*r))))
		goto err_allocs;
 
	r->min_width     = res.min_width;
	r->max_width     = res.max_width;
	r->min_height    = res.min_height;
	r->max_height    = res.max_height;
	r->count_fbs     = res.count_fbs;
	r->count_crtcs   = res.count_crtcs;
	r->count_connectors = res.count_connectors;
	r->count_encoders = res.count_encoders;
 
	r->fbs        = drmAllocCpy(U642VOID(res.fb_id_ptr), res.count_fbs, sizeof(uint32_t));
	r->crtcs      = drmAllocCpy(U642VOID(res.crtc_id_ptr), res.count_crtcs, sizeof(uint32_t));
	r->connectors = drmAllocCpy(U642VOID(res.connector_id_ptr), res.count_connectors, sizeof(uint32_t));
	r->encoders   = drmAllocCpy(U642VOID(res.encoder_id_ptr), res.count_encoders, sizeof(uint32_t));
	if ((res.count_fbs && !r->fbs) ||
	    (res.count_crtcs && !r->crtcs) ||
	    (res.count_connectors && !r->connectors) ||
	    (res.count_encoders && !r->encoders))
	{
		drmFree(r->fbs);
		drmFree(r->crtcs);
		drmFree(r->connectors);
		drmFree(r->encoders);
		drmFree(r);
		r = 0;
	}
 
err_allocs:
	drmFree(U642VOID(res.fb_id_ptr));
	drmFree(U642VOID(res.crtc_id_ptr));
	drmFree(U642VOID(res.connector_id_ptr));
	drmFree(U642VOID(res.encoder_id_ptr));
 
	return r;
}

可以看出,drmModeGetResources函数较长,因此分段来进行解析。

先来看两个结构:struct drm_mode_card_res和drmModeResPtr。

struct drm_mode_card_res前文已经介绍过,为了便于理解,再次贴出源码(include/drm/drm_mode.h中):

struct drm_mode_card_res {
	__u64 fb_id_ptr;
	__u64 crtc_id_ptr;
	__u64 connector_id_ptr;
	__u64 encoder_id_ptr;
	__u32 count_fbs;
	__u32 count_crtcs;
	__u32 count_connectors;
	__u32 count_encoders;
	__u32 min_width;
	__u32 max_width;
	__u32 min_height;
	__u32 max_height;
};

drmModeResPtr在xf86drmMode.h中定义,代码如下:

typedef struct _drmModeRes {

	int count_fbs;
	uint32_t *fbs;

	int count_crtcs;
	uint32_t *crtcs;

	int count_connectors;
	uint32_t *connectors;

	int count_encoders;
	uint32_t *encoders;

	uint32_t min_width, max_width;
	uint32_t min_height, max_height;
} drmModeRes, *drmModeResPtr;

通过这两个结构,就可以看出其中有几个概念:fb、crtc、connector和encoder。实际上前边已经接触过很多次了,只是一直没有专门讲一下。为了后续内容的理解,要把这些概念捋清楚。在此讲一下这些概念以及它们之间的关系。

一切还得从头说起。在本系列开篇的时候,给出了以下架构图:

在这里插入图片描述

图中libdrm是我们本系列的主题,也是目前我们所熟悉的。与之对应的,是更为复杂和核心的概念:DRM。

DRM是Linux目前主流的图形显示框架。资深一些的BSP或驱动工程师应该知道,以前的显示架构为FrameBuffer(简称FB)。相比于FB架构,DRM更能适应当前日益更新的显示硬件。比如FB原生不支持多层合成、不支持VSYNC、不支持DMA-BUF、不支持异步更新、不支持fence机制等等,而这些功能DRM原生都支持。同时DRM可以统一管理GPU和Display驱动,使得软件架构更为统一,方便管理和维护。

DRM从模块上划分,可以简单分为三部分:libdrm、KMS和GEM:

  • libdrm

libdrm的作用之前已经讲过,对底层接口进行封装,向上层提供通用的API接口,主要是对各种IOCTL接口进行封装。

  • KMS

Kernel Mode Setting,内核模式设置(实际上还有个UMS,用户模式设置)。所谓Mode setting,其实说白了就两件事:更新画面和设置显示参数。更新画面包括:显示buffer的切换,多图层的合成方式,以及确定每个图层的显示位置;设置显示参数包括:设置分辨率、刷新率、电源状态(休眠唤醒)等。

  • GEM

Graphic Execution Manager,图形执行管理器。主要负责显示buffer的分配和释放,也是GPU唯一用到DRM的地方。

DRM的KMS和GEM中包含了很多基本元素,大致如下:

KMS包含:CRTC、ENCODER、CONNECTOR、PLANE、FB等。

GEM包含:DUMP、PRIME、fence。

这些元素之间的关系及整体组成如下图所示:

在这里插入图片描述

 再通过如下表格进行详细描述:

元素说明
CRTC对显示buffer进行扫描,并产生时序信号的硬件模块,通常指Display Controller
ENCODER

负责将CRTC输出的timing时序转换成外部设备所需要的信号的模块,如HDMI转换器或

DSI Controller

CONNECTOR

连接物理显示设备的连接器,如HDMI、DisplayPort、DSI总线,通常和Encoder驱动绑定

在一起

PLANE

硬件图层,有的Display硬件支持多层合成显示,但所有的Display Controller至少要有1个

plane

FBFramebuffer,单个图层的显示内容,唯一一个和硬件无关的基本元素
VBLANK软件和硬件的同步机制,RGB时序中的垂直消影区,软件通常使用硬件VSYNC来实现
property

任何你想设置的参数,都可以做成property,是DRM驱动中最灵活、最方便的

Mode setting机制

DUMB只支持连续物理内存,基于kernel中通用CMA API实现,多用于小分辨率简单场景
PRIME

连续、非连续物理内存都支持,基于DMA-BUF机制,可以实现buffer共享,多用于大内存

复杂场景

fencebuffer同步机制,基于内核dma_fence机制实现,用于防止显示内容出现异步问题

弄清楚了以上概念后,下一篇文章继续分析drmModeGetResources函数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/934196.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C语言练习题Day1

从今天开始分享C语言的练习题&#xff0c;每天都分享&#xff0c;差不多持续16天&#xff0c;看完对C语言的理解可能更进一步&#xff0c;让我们开始今天的分享吧&#xff01; 题目一 执行下面的代码&#xff0c;输出结果是&#xff08;&#xff09; int x5,y7; void swap()…

Vue2向Vue3过度核心技术自定义指令

目录 1 自定义指令1.指令介绍2.自定义指令3.自定义指令语法4.指令中的配置项介绍5.代码示例6.总结 2 自定义指令-指令的值1.需求2.语法3.代码示例 3 自定义指令-v-loading指令的封装1.场景2.需求3.分析4.实现5.准备代码 1 自定义指令 1.指令介绍 内置指令&#xff1a;v-html、v…

基于JSP+Servlet+mysql学生宿舍管理系统

基于JSPServletmysql学生宿舍管理系统 一、系统介绍二、功能展示四、其它1.其他系统实现五.获取源码 一、系统介绍 项目类型&#xff1a;Java web项目 项目名称&#xff1a;基于JSPServlet的学生宿舍管理系统[sushe] 项目架构&#xff1a;B/S架构 开发语言&#xff1a;Java…

免费开源跨平台视频下载器 支持数百站点视频和音频下载-ytDownloader

ytDownloader&#xff1a; ytDownloader是一款免费开源跨平台视频下载器&#xff0c;帮助用户从数百个网站下载不同格式的视频和提取音频&#xff0c;使用简单&#xff0c;复制视频链接粘贴即可下载&#xff0c;支持4K画质视频下载&#xff0c;支持Linux、Windows 和 macOS平台…

DBO优化SVM的电力负荷预测,附MATLAB代码

今天为大家带来一期基于DBO-SVM的电力负荷预测。 原理详解 文章对支持向量机(SVM)的两个参数进行优化&#xff0c;分别是&#xff1a;惩罚系数c和 gamma。 其中&#xff0c;惩罚系数c表示对误差的宽容度。c越高&#xff0c;说明越不能容忍出现误差,容易过拟合。c越小&#xff0…

基于Java+SpringBoot+Vue前后端分离图书电子商务网站设计和实现

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

大数据(二)大数据行业相关统计数据

大数据&#xff08;二&#xff09;大数据行业相关统计数据 目录 一、大数据相关的各种资讯 二、转载自网络的大数据统计数据 2.1、国家大数据政策 2.2、产业结构分析 2.3、应用结构分析 2.4、数据中心 2.5、云计算 一、大数据相关的各种资讯 1. 据IDC预测&#xff0…

软件工程(十五) 行为型设计模式(一)

1、责任链模式 简要说明 通过多个对象处理的请求,减少请求的发送者与接收者之间的耦合。将接受对象链接起来,在链中传递请求,直到有一个对象处理这个请求。 速记关键字 传递职责 类图如下 由类图可以比较容易的看出来,其实就是自己关联自己,形成了一个链,并且自己有…

开源与区块链:去中心化的未来

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

基于Java+SpringBoot+Vue前后端分离人力资源管理系统设计和实现

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

【Linux操作系统】Linux系统编程中的互斥锁

文章目录 1. 互斥锁的原理2. 互斥锁的相关函数3. 互斥锁的例子总结 1. 互斥锁的原理 在Linux系统编程中&#xff0c;互斥锁&#xff08;Mutex&#xff09;是一种用于保护共享资源的同步机制。它可以确保在任意时刻只有一个线程可以访问被保护的资源&#xff0c;从而避免了多个…

软件工程(十四) 设计模式之结构型模式(二)

1、组合模式 简要说明 将对象组合成树形结构以表示“整体-部分”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。 速记关键字 树形目录结构 类图如下 由类图其实可以看出,组合模式就是将具有父子关系的结构,组装形成一棵树,并且根据规范,树干节点和叶子节…

大数据Flink(六十八):SQL Table 的基本概念及常用 API

文章目录 SQL & Table 的基本概念及常用 API 一、​​​​​​​一个 Table API\SQL任务的代码结构

tomcat高可用和nginx高可用

tomcat高可用和nginx高可用 小白教程&#xff0c;一看就会&#xff0c;一做就成。 1.什么是高可用&#xff1f; 高可用HA&#xff08;High Availability&#xff09;是分布式系统架构设计中必须考虑的因素之一&#xff0c;它通常是指&#xff0c;通过设计减少系统不能提供服务…

大数据(三)大数据相关的职位

大数据&#xff08;三&#xff09;大数据相关的职位 本文目录&#xff1a; 一、写在前面的题外话 二、2022年就业状况 2.1、不同企业性质高校毕业生 CIER 指数 2.2、不同企业规模高校毕业生 CIER 指数 2.3、高校毕业生供求 TOP15 城市 2.4、一季度景气指数较高和较低的行…

CodeLlama本地部署的实战方案

大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的见解。曾经辅导过若干个非计算机专业的学生进入到算法…

Spring Boot(Vue3+ElementPlus+Axios+MyBatisPlus+Spring Boot 前后端分离)【四】

&#x1f600;前言 本篇博文是关于Spring Boot(Vue3ElementPlusAxiosMyBatisPlusSpring Boot 前后端分离)【四】&#xff0c;希望你能够喜欢 &#x1f3e0;个人主页&#xff1a;晨犀主页 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是晨犀&#xff0c;希望我的文章…

Shell脚本的超详细讲解

目录 一、Shell脚本简介1.1 什么是shell?1.2 什么是shell脚本1.3 shell脚本的意义 二、Shell解析器三、Shell脚本入门四、Shell中的变量4.1 系统变量4.2 自定义变量4.3 特殊变量&#xff1a;$n4.4 特殊变量&#xff1a;$#4.5 特殊变量&#xff1a; $*、$4.6 特殊变量&#xff…

本地部署 CodeLlama 并在 VSCode 中使用 CodeLlama

本地部署 CodeLlama 并在 VSCode 中使用 CodeLlama 1. CodeLlama 是什么2. CodeLlama Github 地址3. 下载 CodeLlama 模型4. 部署 CodeLlama5. 在 VSCode 中使用 CodeLlama 1. CodeLlama 是什么 Code Llama 是一个基于 Llama 2 的大型代码语言模型系列&#xff0c;在开放模型、…

《深入理解Java虚拟机》读书笔记:基于栈的字节码解释执行引擎

虚拟机是如何调用方法的内容已经讲解完毕&#xff0c;从本节开始&#xff0c;我们来探讨虚拟机是如何执行方法中的字节码指令的。上文中提到过&#xff0c;许多Java虚拟机的执行引擎在执行Java代码的时候都有解释执行&#xff08;通过解释器执行&#xff09;和编译执行&#xf…