DRM系列八:Drm之DRM_IOCTL_MODE_ADDFB2
本系列文章基于linux 5.15
在上一篇文章DRM系列七:Drm之DRM_IOCTL_MODE_CREATE_DUMB获取buf的handle和pitch之后,接着使用ioctl(fd, DRM_IOCTL_MODE_ADDFB2, &fb_cmd)创建一个新的帧缓冲区对象(framebuffer object),并将帧缓冲区对象与显存关联起来。
一、整体流程
用户层提供width、height、piexel_format、handle和pitch,然后调用ioctl(fd, DRM_IOCTL_MODE_ADDFB2, &fb_cmd)进入kernel层,调用drm_mode_addfb2_ioctl创建新的帧缓冲区对象(framebuffer object),并将其与显存中的一块内存区域关联起来,返回fb_id供用户层使用。其关系如下图所示:

1.drm_mode_addfb2_ioctl
主要作用是为用户空间的应用程序创建一个新的帧缓冲区对象(framebuffer object),并将其与显存中的一块内存区域关联起来。
DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB2, drm_mode_addfb2_ioctl, 0),int drm_mode_addfb2_ioctl(struct drm_device *dev,void *data, struct drm_file *file_priv)
{
#ifdef __BIG_ENDIANif (!dev->mode_config.quirk_addfb_prefer_host_byte_order) {DRM_DEBUG_KMS("addfb2 broken on bigendian");return -EOPNOTSUPP;}
#endifreturn drm_mode_addfb2(dev, data, file_priv);
}
int drm_mode_addfb2(struct drm_device *dev,void *data, struct drm_file *file_priv)
{struct drm_mode_fb_cmd2 *r = data;struct drm_framebuffer *fb;if (!drm_core_check_feature(dev, DRIVER_MODESET))return -EOPNOTSUPP;fb = drm_internal_framebuffer_create(dev, r, file_priv);if (IS_ERR(fb))return PTR_ERR(fb);/*将新创建的 framebuffer 的 ID 存储到用户空间传递的 drm_mode_fb_cmd2 结构中,以便用户空间可以引用该 framebuffer*/DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id);r->fb_id = fb->base.id;/* 帧缓冲区被添加到drm_file(file_priv)拥有的帧缓冲区列表中 */mutex_lock(&file_priv->fbs_lock);list_add(&fb->filp_head, &file_priv->fbs);mutex_unlock(&file_priv->fbs_lock);return 0;
}
1.1drm_internal_framebuffer_create
创建一个 drm_framebuffer 对象并初始化;接着会调用 framebuffer_check 函数对传入的参数进行检查,确保参数有效;最后调用dev->mode_config.funcs->fb_create回调,返回一个 drm_framebuffer 对象。
struct drm_framebuffer *drm_internal_framebuffer_create(struct drm_device *dev,const struct drm_mode_fb_cmd2 *r,struct drm_file *file_priv)
{struct drm_mode_config *config = &dev->mode_config;struct drm_framebuffer *fb;int ret;if (r->flags & ~(DRM_MODE_FB_INTERLACED | DRM_MODE_FB_MODIFIERS)) {DRM_DEBUG_KMS("bad framebuffer flags 0x%08x\n", r->flags);return ERR_PTR(-EINVAL);}/*mode_config的min_width和min_height和帧缓冲区对象的width和height的限制*/if ((config->min_width > r->width) || (r->width > config->max_width)) {DRM_DEBUG_KMS("bad framebuffer width %d, should be >= %d && <= %d\n",r->width, config->min_width, config->max_width);return ERR_PTR(-EINVAL);}if ((config->min_height > r->height) || (r->height > config->max_height)) {DRM_DEBUG_KMS("bad framebuffer height %d, should be >= %d && <= %d\n",r->height, config->min_height, config->max_height);return ERR_PTR(-EINVAL);}if (r->flags & DRM_MODE_FB_MODIFIERS &&!dev->mode_config.allow_fb_modifiers) {DRM_DEBUG_KMS("driver does not support fb modifiers\n");return ERR_PTR(-EINVAL);}/*对传入的参数进行检查,确保参数有效*/ret = framebuffer_check(dev, r);if (ret)return ERR_PTR(ret);/*调用mode_config func的fb_create回调*/fb = dev->mode_config.funcs->fb_create(dev, file_priv, r);if (IS_ERR(fb)) {DRM_DEBUG_KMS("could not create framebuffer\n");return fb;}return fb;
}
1.1.1framebuffer_check
对传入的参数进行检查,确保参数有效。
static int framebuffer_check(struct drm_device *dev,const struct drm_mode_fb_cmd2 *r)
{const struct drm_format_info *info;int i;/* check if the format is supported at all */if (!__drm_format_info(r->pixel_format)) {DRM_DEBUG_KMS("bad framebuffer format %p4cc\n",&r->pixel_format);return -EINVAL;}if (r->width == 0) {DRM_DEBUG_KMS("bad framebuffer width %u\n", r->width);return -EINVAL;}if (r->height == 0) {DRM_DEBUG_KMS("bad framebuffer height %u\n", r->height);return -EINVAL;}/* 获取与之相关的像素格式信息 */info = drm_get_format_info(dev, r);for (i = 0; i < info->num_planes; i++) {unsigned int width = fb_plane_width(r->width, info, i);unsigned int height = fb_plane_height(r->height, info, i);unsigned int block_size = info->char_per_block[i];u64 min_pitch = drm_format_info_min_pitch(info, i, width);if (!block_size && (r->modifier[i] == DRM_FORMAT_MOD_LINEAR)) {DRM_DEBUG_KMS("Format requires non-linear modifier for plane %d\n", i);return -EINVAL;}if (!r->handles[i]) {DRM_DEBUG_KMS("no buffer object handle for plane %d\n", i);return -EINVAL;}if (min_pitch > UINT_MAX)return -ERANGE;if ((uint64_t) height * r->pitches[i] + r->offsets[i] > UINT_MAX)return -ERANGE;if (block_size && r->pitches[i] < min_pitch) {DRM_DEBUG_KMS("bad pitch %u for plane %d\n", r->pitches[i], i);return -EINVAL;}if (r->modifier[i] && !(r->flags & DRM_MODE_FB_MODIFIERS)) {DRM_DEBUG_KMS("bad fb modifier %llu for plane %d\n",r->modifier[i], i);return -EINVAL;}if (r->flags & DRM_MODE_FB_MODIFIERS &&r->modifier[i] != r->modifier[0]) {DRM_DEBUG_KMS("bad fb modifier %llu for plane %d\n",r->modifier[i], i);return -EINVAL;}/* modifier specific checks: */switch (r->modifier[i]) {case DRM_FORMAT_MOD_SAMSUNG_64_32_TILE:/* NOTE: the pitch restriction may be lifted later if it turns* out that no hw has this restriction:*/if (r->pixel_format != DRM_FORMAT_NV12 ||width % 128 || height % 32 ||r->pitches[i] % 128) {DRM_DEBUG_KMS("bad modifier data for plane %d\n", i);return -EINVAL;}break;default:break;}}for (i = info->num_planes; i < 4; i++) {if (r->modifier[i]) {DRM_DEBUG_KMS("non-zero modifier for unused plane %d\n", i);return -EINVAL;}/* Pre-FB_MODIFIERS userspace didn't clear the structs properly. */if (!(r->flags & DRM_MODE_FB_MODIFIERS))continue;if (r->handles[i]) {DRM_DEBUG_KMS("buffer object handle for unused plane %d\n", i);return -EINVAL;}if (r->pitches[i]) {DRM_DEBUG_KMS("non-zero pitch for unused plane %d\n", i);return -EINVAL;}if (r->offsets[i]) {DRM_DEBUG_KMS("non-zero offset for unused plane %d\n", i);return -EINVAL;}}return 0;
}
1.1.1.1drm_get_format_info
用于根据用户空间提供的 framebuffer 创建请求(drm_mode_fb_cmd2),获取与之相关的像素格式信息。在这里会使用dev->mode_config.funcs->get_format_info回调。
const struct drm_format_info *drm_get_format_info(struct drm_device *dev,const struct drm_mode_fb_cmd2 *mode_cmd)
{const struct drm_format_info *info = NULL;if (dev->mode_config.funcs->get_format_info)info = dev->mode_config.funcs->get_format_info(mode_cmd);if (!info)info = drm_format_info(mode_cmd->pixel_format);return info;
}
相关文章:
DRM系列八:Drm之DRM_IOCTL_MODE_ADDFB2
本系列文章基于linux 5.15 在上一篇文章DRM系列七:Drm之DRM_IOCTL_MODE_CREATE_DUMB获取buf的handle和pitch之后,接着使用ioctl(fd, DRM_IOCTL_MODE_ADDFB2, &fb_cmd)创建一个新的帧缓冲区对象(framebuffer object),并将帧缓冲区对象与显…...
软件测试用例篇
设计测试用例是测试面试的必考题,务必好好学 1. 测试用例 测试用例的概念 测试⽤例(Test Case)是为了实施测试而向被测试的系统提供的⼀组集合,这组集合包含:测试环境、操作步骤、测试数据、预期结果等要素。 设计测试⽤…...
PopupMenuButton组件的功能和用法
文章目录 1 概念介绍2 使用方法3 示例代码 我们在上一章回中介绍了Sliver综合示例相关的内容,本章回中将介绍PopupMenuButton组件.闲话休提,让我们一起Talk Flutter吧。 1 概念介绍 我们在本章回中介绍的PopupMenuButton组件位于AppBar右侧,…...
Python进行模型优化与调参
在数据科学与机器学习领域,模型的优化与调参是提高模型性能的重要步骤之一。模型优化可以帮助提高模型的准确性和泛化能力,而合理的调参则能够充分发挥模型的潜力。这篇教程将重点介绍几种常用的模型优化与调参方法,特别是超参数调整和正则化技术的应用。这些技术能够有效地…...
vue2-组件通信
文章目录 vue2-组件通信1. 为什么需要组件通信2. props传递数据3. $emit触发自定义事件4.ref5. EventBus6. p a r e n t 和 parent和 parent和root7. a t t r s 和 attrs和 attrs和listeners8. provide和inject9. vuex10. 总结 vue2-组件通信 1. 为什么需要组件通信 在VUE中…...
20250205确认荣品RK3566开发板在Android13下可以使用命令行reboot -p关机
20250205确认荣品RK3566开发板在Android13下可以使用命令行reboot -p关机 2025/2/5 16:10 缘起:荣品RK3566开发板在Android13下,希望通过Native C语言程序来控制RK3566的关机。 通过ADB,很容易通过reboot -p命令关机。 最开始以为需要su/root…...
设计模式---观察者模式
设计模式—观察者模式 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。 主要解决的问题:一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,…...
初八开工!开启数字化转型新征程!
新年新气象,大年初八,我们斗志昂扬,共同奔赴充满希望的新一年! 2025 年意义非凡,这是广州市开利网络科技有限公司成立的第 18 个年头 。回首过往,我们一路拼搏,一路成长,积累了深厚的…...
文本分析NLP的常用工具和特点
1)非上下文感知型文本分析工具和特点 特性VADERTextBlob适合文本类型短文本、非正式语言(如评论、推文)中等长度、正式文本情感强度分析支持(正面、负面、中性)支持(极行、主观性)处理表情符号…...
DeepSeek 与 ChatGPT 对比分析
一、技术背景与研发团队 ChatGPT 由 OpenAI 开发,自 2015 年 OpenAI 成立以来,经过多年的技术积累和迭代,从 GPT-1 到 GPT-4o,每一次升级都带来了技术上的突破。OpenAI 拥有雄厚的技术实力和海量的数据、强大的算力支持ÿ…...
vite---依赖优化选项esbuildOptions详解
optimizeDeps.esbuildOptions vite.optimizeDeps.esbuildOptions 是 Vite 配置中的一个选项,它允许你在 Vite 启动时,给 esbuild(Vite 用来处理代码转换和优化的工具)传递额外的配置。通过这个配置项,你可以自定义 esb…...
ElasticSearch 学习课程入门(二)
引子 前文已经介绍了ES的增删改查基本操作,接下来,我们学习下高级点的用法。OK,那就让我们开始吧。 一、ES高级操作 1、条件查询 (1)GET https://127.0.0.1:9200/shopping/_search?qcategory:小米 (2&…...
使用 Redis Streams 实现高性能消息队列
1. 引言 在后端开发中,消息队列是一个常见的组件,主要用于解耦系统、提高吞吐量以及实现异步处理。常见的消息队列包括 Kafka、RabbitMQ 以及 ActiveMQ,但 Redis Streams 作为 Redis 5.0 引入的新特性,也提供了一种高效、轻量的消…...
深度学习|表示学习|卷积神经网络|DeconvNet是什么?|18
如是我闻: DeconvNet(反卷积网络)是一种可视化 CNN(卷积神经网络)内部特征的方法,用于理解 CNN 是如何提取图像特征的。这个方法由 Zeiler & Fergus(2013) 提出,目的…...
(优先级队列(堆)) 【本节目标】 1. 掌握堆的概念及实现 2. 掌握 PriorityQueue 的使用
优先级队列(堆) 1. 优先级队列1.1 概念 2. 优先级队列的模拟实现2.1 堆的概念2.2 堆的存储方式2.3 堆的创建2.3.1 堆向下调整2.3.2 堆的创建2.3.3 建堆的时间复杂度 【本节目标】 掌握堆的概念及实现掌握 PriorityQueue 的使用 1. 优先级队列 1.1 概念…...
优化数据库结构
MySQL学习大纲 一个好的数据库设计方案对于数据库的性能尝尝会起到事倍功半的效果,合理的数据库结构不仅使数据库占用更小的磁盘空间,而且使查询速度更快。数据库结构的设计需要考虑数据冗余、查询和更新速度、字段的数据类型是否合理等多方面的内容&…...
密云生活的初体验
【】在《岁末随笔之碎碎念》里,我通告了自己搬新家的事情。乙巳年开始,我慢慢与大家分享自己买房装修以及在新家的居住体验等情况。 跳过买房装修的内容,今天先说说这三个月的生活体验。 【白河】 潮白河是海河水系五大河之一,贯穿…...
图像分类与目标检测算法
在计算机视觉领域,图像分类与目标检测是两项至关重要的技术。它们通过对图像进行深入解析和理解,为各种应用场景提供了强大的支持。本文将详细介绍这两项技术的算法原理、技术进展以及当前的落地应用。 一、图像分类算法 图像分类是指将输入的图像划分为…...
计算机网络——流量控制
流量控制的基本方法是确保发送方不会以超过接收方处理能力的速度发送数据包。 通常的做法是接收方会向发送方提供某种反馈,如: (1)停止&等待 在任何时候只有一个数据包在传输,发送方发送一个数据包,…...
体验 DeepSeek 多模态大模型 Janus-Pro-7B
含有图片的链接: https://mp.weixin.qq.com/s/i6kuVcGU1CUMYRPDM-bKog?token2020918682&langzh_CN 继上篇文章下载了 Janus-Pro-7B 后,准备本地运行时发现由于电脑配置配置太低(显存小于24G),无法运行࿰…...
树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频
使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...
ssc377d修改flash分区大小
1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...
Python实现prophet 理论及参数优化
文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...
什么是EULA和DPA
文章目录 EULA(End User License Agreement)DPA(Data Protection Agreement)一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA(End User License Agreement) 定义: EULA即…...
PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...
土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等
🔍 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术,可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势,还能有效评价重大生态工程…...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...
