当前位置: 首页 > news >正文

Linux内核4.14版本——drm框架分析(11)——DRM_IOCTL_MODE_ADDFB2(drm_mode_addfb2)

目录

1. drm_mode_addfb2

2. drm_internal_framebuffer_create

3. drm_fb_cma_create->drm_gem_fb_create->drm_gem_fb_create_with_funcs

4. drm_gem_fb_alloc

 4.1 drm_helper_mode_fill_fb_struct

4.2 drm_framebuffer_init

5. 调用流程图


        书接上回,使用drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &create)接口创建了一块内存放在了gem cma的对象里。

        gem obj创建之后需要与一块drm_framebuffer进行绑定使用,因为最终刷图使用的是fb。使用下面接口会创建drm_framebuffer并与上节创建的gem obj进行绑定。

        目前使用较多的就是drm_mode_addfb2接口,该接口完成了下面的功能。

1. drm_mode_addfb2

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 -EINVAL;fb = drm_internal_framebuffer_create(dev, r, file_priv);if (IS_ERR(fb))return PTR_ERR(fb);DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id);r->fb_id = fb->base.id;/* Transfer ownership to the filp for reaping on close */mutex_lock(&file_priv->fbs_lock);list_add(&fb->filp_head, &file_priv->fbs);mutex_unlock(&file_priv->fbs_lock);return 0;
}

       drm_mode_addfb2主要做了三件大事:

        (1)调用drm_internal_framebuffer_create创建一个drm_framebuffer。

        (2)把drm_framebuffer的struct drm_mode_object的ID返回给应用。

        (3)加到file_priv的fbs链表中。

下面我们看一下函数drm_internal_framebuffer_create。

2. drm_internal_framebuffer_create

struct drm_framebuffer *
drm_internal_framebuffer_create(struct drm_device *dev,const struct drm_mode_fb_cmd2 *r,struct drm_file *file_priv)
{........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;
}

        检查参数,然后调用dev->mode_config.funcs->fb_create(dev, file_priv, r),可以自己实现,也可以使用内核现成的drm_fb_cma_create。

3. drm_fb_cma_create->drm_gem_fb_create->drm_gem_fb_create_with_funcs


struct drm_framebuffer *
drm_gem_fb_create_with_funcs(struct drm_device *dev, struct drm_file *file,const struct drm_mode_fb_cmd2 *mode_cmd,const struct drm_framebuffer_funcs *funcs)
{const struct drm_format_info *info;struct drm_gem_object *objs[4];struct drm_framebuffer *fb;int ret, i;info = drm_get_format_info(dev, mode_cmd);if (!info)return ERR_PTR(-EINVAL);for (i = 0; i < info->num_planes; i++) {unsigned int width = mode_cmd->width / (i ? info->hsub : 1);unsigned int height = mode_cmd->height / (i ? info->vsub : 1);unsigned int min_size;objs[i] = drm_gem_object_lookup(file, mode_cmd->handles[i]);if (!objs[i]) {DRM_DEV_ERROR(dev->dev, "Failed to lookup GEM\n");ret = -ENOENT;goto err_gem_object_put;}min_size = (height - 1) * mode_cmd->pitches[i]+ width * info->cpp[i]+ mode_cmd->offsets[i];if (objs[i]->size < min_size) {// DRM_DEV_ERROR(dev->dev, "objs %d Size(%d %d) error\n",// 	i, objs[i]->size, min_size);drm_gem_object_put_unlocked(objs[i]);ret = -EINVAL;goto err_gem_object_put;}}fb = drm_gem_fb_alloc(dev, mode_cmd, objs, i, funcs);if (IS_ERR(fb)) {ret = PTR_ERR(fb);DRM_DEV_ERROR(dev->dev, "alloc error %d\n", ret);goto err_gem_object_put;}return fb;err_gem_object_put:for (i--; i >= 0; i--)drm_gem_object_put_unlocked(objs[i]);return ERR_PTR(ret);
}

        (1)通过应用提供的handle,使用drm_gem_object_lookup找到上次创建的gem obj。

        (2)调用drm_gem_fb_alloc,分配一个drm_framebuffer,将gem obj赋值给framebuffer中的obj。

4. drm_gem_fb_alloc

static struct drm_framebuffer *
drm_gem_fb_alloc(struct drm_device *dev,const struct drm_mode_fb_cmd2 *mode_cmd,struct drm_gem_object **obj, unsigned int num_planes,const struct drm_framebuffer_funcs *funcs)
{struct drm_framebuffer *fb;int ret, i;fb = kzalloc(sizeof(*fb), GFP_KERNEL);if (!fb)return ERR_PTR(-ENOMEM);drm_helper_mode_fill_fb_struct(dev, fb, mode_cmd);for (i = 0; i < num_planes; i++)fb->obj[i] = obj[i];ret = drm_framebuffer_init(dev, fb, funcs);if (ret) {DRM_DEV_ERROR(dev->dev, "Failed to init framebuffer: %d\n",ret);kfree(fb);return ERR_PTR(ret);}return fb;
}

 4.1 drm_helper_mode_fill_fb_struct

void drm_helper_mode_fill_fb_struct(struct drm_device *dev,struct drm_framebuffer *fb,const struct drm_mode_fb_cmd2 *mode_cmd)
{int i;fb->dev = dev;fb->format = drm_get_format_info(dev, mode_cmd);fb->width = mode_cmd->width;fb->height = mode_cmd->height;for (i = 0; i < 4; i++) {fb->pitches[i] = mode_cmd->pitches[i];fb->offsets[i] = mode_cmd->offsets[i];}fb->modifier = mode_cmd->modifier[0];fb->flags = mode_cmd->flags;
}

      将应用传入的长,宽,format,pitch,flag等填充framebuffer结构体。

4.2 drm_framebuffer_init

int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb,const struct drm_framebuffer_funcs *funcs)
{int ret;if (WARN_ON_ONCE(fb->dev != dev || !fb->format))return -EINVAL;INIT_LIST_HEAD(&fb->filp_head);fb->funcs = funcs;ret = __drm_mode_object_add(dev, &fb->base, DRM_MODE_OBJECT_FB,false, drm_framebuffer_free);if (ret)goto out;mutex_lock(&dev->mode_config.fb_lock);dev->mode_config.num_fb++;list_add(&fb->head, &dev->mode_config.fb_list);mutex_unlock(&dev->mode_config.fb_lock);drm_mode_object_register(dev, &fb->base);
out:return ret;
}

        相关字段填充完成后会将fb添加进dev->mode_config.fb_list便于后面使用的时候通过id进行查找, drm的组件都是通过dev->mode_config中的链表进行管理的,只要拿到mode_config就可以拿到drm相关信息。

        至此drm_framebuffer已经创建完毕。通过r->fb_id = fb->base.id;将fb_id返回给用户。

5. 调用流程图

http://www.lryc.cn/news/166030.html

相关文章:

  • mysql的date_format()函数格式月份的坑
  • 保姆级式教程:教你制作电子画册
  • 探究Nginx应用场景
  • sklearn中的数据集使用
  • LLM在电商推荐系统的探索与实践
  • Linux 文本操作指令
  • GIS地图服务数据可视化
  • java 获取实体类的反射 Field用法(获取对象的字段名和属性值) 包含注解值 - 如何用枚举类映射获取数据库字段名
  • 日志平台搭建第六章:logstash通过kafka通道采集日志信息
  • mysql的索引分类
  • 【校招VIP】java语言考点之并发相关
  • nginx实现路由重定向功能 避免服务器出现 404 Not Found
  • Flask+pyecharts+SQLAlchemy,统计图的数据存放在mysql中,综合版
  • SQL注入类型判断
  • ElasticSearch的安装部署-----图文介绍
  • Unity粒子系统ParticleSystem各模块及其参数学习
  • vue3实现卡片翻牌
  • 算法训练营day45|动态规划 part07:完全背包 (LeetCode 70. 爬楼梯(进阶)、322. 零钱兑换、279.完全平方数)
  • 【大模型】更强的开源可商用的中英文大语言模型baichuan2来了,从零开始搭建
  • ElasticSearch系列-简介与安装详解
  • Layui + Flask | 表单组件(组件篇)(07)
  • 【实践篇】Redis最强Java客户端Redisson
  • esxi扩容磁盘
  • 核心实验21_BGP高级(了解)(配置略)_ENSP
  • 宝塔安装python和openssl
  • TDengine 3.1.1.0 来啦!更新如下
  • YSA Toon (Anime/Toon Shader)
  • LabVIEW通过IEC61508标准验证ITER联锁系统
  • 如何处理日期和时间?
  • 【开发】视频集中存储/直播点播平台EasyDSS点播文件分类功能优化