Android12之DRM基本接口实现(二)

news2025/1/13 10:31:01

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长!

优质专栏:Audio工程师进阶系列原创干货持续更新中……】🚀

人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.

更多原创,欢迎关注:Android系统攻城狮

欢迎关注Android系统攻城狮

1.前言

本篇目的:探究DRM基本接口的实现,底层实现到底是如何与DRM驱动通信的?

2.DRM基本接口实现解析

<1>.DRM之drmModeGetResources获取CRTC和Connector的id号

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;
}

核心要点1

1.调用drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res)获取CRTC和Connector的id号。

2.drm_mode_card_res数据结构

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;
};

<2>.DRM之drmModeGetConnector连接Connector显示器

static drmModeConnectorPtr
_drmModeGetConnector(int fd, uint32_t connector_id, int probe)
{
	struct drm_mode_get_connector conn, counts;
	drmModeConnectorPtr r = NULL;
	struct drm_mode_modeinfo stack_mode;

	memclear(conn);
	conn.connector_id = connector_id;
	if (!probe) {
		conn.count_modes = 1;
		conn.modes_ptr = VOID2U64(&stack_mode);
	}

	if (drmIoctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn))
		return 0;

retry:
	counts = conn;

	if (conn.count_props) {
		conn.props_ptr = VOID2U64(drmMalloc(conn.count_props*sizeof(uint32_t)));
		if (!conn.props_ptr)
			goto err_allocs;
		conn.prop_values_ptr = VOID2U64(drmMalloc(conn.count_props*sizeof(uint64_t)));
		if (!conn.prop_values_ptr)
			goto err_allocs;
	}

	if (conn.count_modes) {
		conn.modes_ptr = VOID2U64(drmMalloc(conn.count_modes*sizeof(struct drm_mode_modeinfo)));
		if (!conn.modes_ptr)
			goto err_allocs;
	} else {
		conn.count_modes = 1;
		conn.modes_ptr = VOID2U64(&stack_mode);
	}

	if (conn.count_encoders) {
		conn.encoders_ptr = VOID2U64(drmMalloc(conn.count_encoders*sizeof(uint32_t)));
		if (!conn.encoders_ptr)
			goto err_allocs;
	}

	if (drmIoctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn))
		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_props < conn.count_props ||
	    counts.count_modes < conn.count_modes ||
	    counts.count_encoders < conn.count_encoders) {
		drmFree(U642VOID(conn.props_ptr));
		drmFree(U642VOID(conn.prop_values_ptr));
		if (U642VOID(conn.modes_ptr) != &stack_mode)
			drmFree(U642VOID(conn.modes_ptr));
		drmFree(U642VOID(conn.encoders_ptr));

		goto retry;
	}

	if(!(r = drmMalloc(sizeof(*r)))) {
		goto err_allocs;
	}

	r->connector_id = conn.connector_id;
	r->encoder_id = conn.encoder_id;
	r->connection   = conn.connection;
	r->mmWidth      = conn.mm_width;
	r->mmHeight     = conn.mm_height;
	/* convert subpixel from kernel to userspace */
	r->subpixel     = conn.subpixel + 1;
	r->count_modes  = conn.count_modes;
	r->count_props  = conn.count_props;
	r->props        = drmAllocCpy(U642VOID(conn.props_ptr), conn.count_props, sizeof(uint32_t));
	r->prop_values  = drmAllocCpy(U642VOID(conn.prop_values_ptr), conn.count_props, sizeof(uint64_t));
	r->modes        = drmAllocCpy(U642VOID(conn.modes_ptr), conn.count_modes, sizeof(struct drm_mode_modeinfo));
	r->count_encoders = conn.count_encoders;
	r->encoders     = drmAllocCpy(U642VOID(conn.encoders_ptr), conn.count_encoders, sizeof(uint32_t));
	r->connector_type  = conn.connector_type;
	r->connector_type_id = conn.connector_type_id;

	if ((r->count_props && !r->props) ||
	    (r->count_props && !r->prop_values) ||
	    (r->count_modes && !r->modes) ||
	    (r->count_encoders && !r->encoders)) {
		drmFree(r->props);
		drmFree(r->prop_values);
		drmFree(r->modes);
		drmFree(r->encoders);
		drmFree(r);
		r = 0;
	}

err_allocs:
	drmFree(U642VOID(conn.prop_values_ptr));
	drmFree(U642VOID(conn.props_ptr));
	if (U642VOID(conn.modes_ptr) != &stack_mode)
		drmFree(U642VOID(conn.modes_ptr));
	drmFree(U642VOID(conn.encoders_ptr));

	return r;
}

核心要点2

1.drmIoctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn):连接CONNECTOR到显示器

2.drm_mode_get_connector数据结构

struct drm_mode_get_connector {
  __u64 encoders_ptr;
  __u64 modes_ptr;
  __u64 props_ptr;
  __u64 prop_values_ptr;
  __u32 count_modes;
  __u32 count_props;
  __u32 count_encoders;
  __u32 encoder_id;
  __u32 connector_id;
  __u32 connector_type;
  __u32 connector_type_id;
  __u32 connection;
  __u32 mm_width;
  __u32 mm_height;
  __u32 subpixel;
  __u32 pad;
};

<3>.DRM之modeset_create_fb添加framebuffer设备

static int modeset_create_fb(int fd, struct buffer_object *bo) {
  struct drm_mode_create_dumb create = {};
  struct drm_mode_map_dumb map = {};

  create.width = bo->width;
  create.height = bo->height;
  create.bpp = 32;
  drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &create);
  printf("create dumb w %d h %d\n", bo->width, bo->height);
  getchar();

  bo->pitch = create.pitch;
  bo->size = create.size;
  bo->handle = create.handle;
  drmModeAddFB(fd, bo->width, bo->height, 24, 32, bo->pitch, bo->handle,
               &bo->fb_id);
  printf("drmModeAddFB\n");
  getchar();

  map.handle = create.handle;
  drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &map);
  printf("map dumb\n");
  getchar();
  bo->vaddr = static_cast<unsigned char *>(mmap64(
      0, create.size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, map.offset));
  memset(bo->vaddr, 0xff, bo->size);
  return 0;
}

核心要点3

1.drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &create): 增加申请DUMB共享内存
2.drmModeAddFB(fd, bo->width, bo->height, 24, 32, bo->pitch, bo->handle,&bo->fb_id);
DRM_IOCTL(fd, DRM_IOCTL_MODE_ADDFB, &f);:添加一个FrameBuffer
3.bo->vaddr = static_cast<unsigned char *>(mmap64( 0, create.size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, map.offset));:映射DRM图形buffer的共享内存到bo->vaddr地址。
memset(bo->vaddr, 0xff, bo->size);:设置白色。
4.drm_mode_create_dumb和drm_mode_map_dumb数据结构

struct drm_mode_create_dumb {
  __u32 height;
  __u32 width;
  __u32 bpp;
  __u32 flags;
  __u32 handle;
  __u32 pitch;
  __u64 size;
};

struct drm_mode_map_dumb {
  __u32 handle;
  __u32 pad;
  __u64 offset;
};

<4>.DRM之drmModeSetCrtcCRTC开始扫描framebuffer数据显示

drm_public int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId,
		   uint32_t x, uint32_t y, uint32_t *connectors, int count,
		   drmModeModeInfoPtr mode)
{
	struct drm_mode_crtc crtc;

	memclear(crtc);
	crtc.x             = x;
	crtc.y             = y;
	crtc.crtc_id       = crtcId;
	crtc.fb_id         = bufferId;
	crtc.set_connectors_ptr = VOID2U64(connectors);
	crtc.count_connectors = count;
	if (mode) {
	  memcpy(&crtc.mode, mode, sizeof(struct drm_mode_modeinfo));
	  crtc.mode_valid = 1;
	}

	return DRM_IOCTL(fd, DRM_IOCTL_MODE_SETCRTC, &crtc);
}

核心要点4

1.DRM_IOCTL(fd, DRM_IOCTL_MODE_SETCRTC, &crtc):CRTC对framebuffer的数据进行扫描

2.drm_mode_crtc数据结构

struct drm_mode_crtc {
  __u64 set_connectors_ptr;
  __u32 count_connectors;
  __u32 crtc_id;
  __u32 fb_id;
  __u32 x;
  __u32 y;
  __u32 gamma_size;
  __u32 mode_valid;
  struct drm_mode_modeinfo mode;
};


<5>.DRM之modeset_destroy_fb关闭framebuffer设备

static void modeset_destroy_fb(int fd, struct buffer_object *bo) {
  struct drm_mode_destroy_dumb destroy = {};

  drmModeRmFB(fd, bo->fb_id);
  munmap(bo->vaddr, bo->size);
  destroy.handle = bo->handle;
  drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy);
}

核心要点5

1.drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy);:销毁DUMB共享内存

2.drm_mode_destroy_dumb数据结构

struct drm_mode_destroy_dumb {
  __u32 handle;
};


<6>.DRM之drmModeFreeConnector断开Connector连接

drm_public void drmModeFreeConnector(drmModeConnectorPtr ptr)
{
	if (!ptr)
		return;

	drmFree(ptr->encoders);
	drmFree(ptr->prop_values);
	drmFree(ptr->props);
	drmFree(ptr->modes);
	drmFree(ptr);
}

核心要点6

1.调用drmFree释放内存,内部调用free()函数。

2.drmFree函数实现

drm_public void drmFree(void *pt)
{
    free(pt);
}


<7>.DRM之drmModeFreeResources释放资源

drm_public void drmModeFreeResources(drmModeResPtr ptr)
{
	if (!ptr)
		return;

	drmFree(ptr->fbs);
	drmFree(ptr->crtcs);
	drmFree(ptr->connectors);
	drmFree(ptr->encoders);
	drmFree(ptr);
}

核心要点7

1.调用drmFree释放资源,本质和drmModeFreeConnector一样,也是释放内存资源。

3.DRM基本接口总结

  • 1.drmModeGetResources函数调用DRM驱动通过ioctl(DRM_IOCTL_MODE_GETRESOURCES):获取CRTC和Connector的id号。
  • 2.drmModeGetConnector函数调用ioctl(DRM_IOCTL_MODE_GETCONNECTOR):连接CONNECTOR到显示器
  • 3.modeset_create_fb函数调用ioctl(DRM_IOCTL_MODE_ADDFB):添加一个FrameBuffer
  • 4.drmModeSetCrtc函数调用ioctl(DRM_IOCTL_MODE_SETCRTC):CRTC对framebuffer的数据进行扫描
  • 5.modeset_destroy_fb函数调用ioctl(DRM_IOCTL_MODE_DESTROY_DUMB):销毁DUMB共享内存
  • 6.drmModeFreeConnector函数调用drmFree释放内存资源
  • 7.drmModeFreeResources函数调用drmFree释放内存资源

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

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

相关文章

Android性能优化系列-腾讯matrix-流量监控之TrafficPlugin源码分析

前言 本篇进行matrix框架的网络流量监控模块的代码分析。你可能想&#xff0c;为什么需要对流量进行监控呢&#xff1f;我们平常进行的网络接口请求都是一些必要的操作&#xff0c;监控它的意义何在&#xff1f;首先我们要明确流量监控的对象是什么&#xff0c;是上行&#xf…

【学习笔记】RabbitMQ-5 消息的可靠性投递 以及示例代码

参考资料 RabbitMQ官方网站RabbitMQ官方文档噼咔噼咔-动力节点教程 文章目录 八、RabbitMQ的确认机制 -confirm8.1 Confirm 模式简介8.2 具体代码设置8.2.1 **设置思路**&#xff1a;8.2.2 **代码实现**8.2.2.1 开启生产者的确认模式.8.2.2.2 实现接口ComfirmCallback8.2.2.3 配…

Transformer模型 | Transformer模型描述

谷歌推出的BERT模型在11项NLP任务中夺得SOTA结果,引爆了整个NLP界。而BERT取得成功的一个关键因素是Transformer的强大作用。谷歌的Transformer模型最早是用于机器翻译任务,当时达到了SOTA效果。Transformer改进了RNN最被人诟病的训练慢的缺点,利用self-attention机制实现快…

浪涌防护:TSS管的工作原理与应用?|深圳比创达EMC

浪涌防护&#xff1a;TSS管的工作原理与应用&#xff1f;相信不少人是有疑问的&#xff0c;今天深圳市比创达电子科技有限公司就跟大家解答一下&#xff01; 一、TSS工作原理 TSS半导体放电管是一种电压开关型瞬态抑制二极管&#xff0c;即涌压抑制晶体管&#xff0c;或称为导…

大中小企业自招人力及劳务派遣招聘

抖音直播招聘报白是一种通过直播方式展示职位信息并与求职者互动的招聘方式。在抖音平台上&#xff0c;企业或人力资源公司可利用直播将职位以视频直播的方式展现&#xff0c;这种方式可给求职者带来更强的代入感和真实性&#xff0c;解决其对岗位真假难辨的信任问题。 图片 …

SCB-Dataset3 公开 学生课堂行为数据集: A Benchmark for Detecting Student Classroom Behavior

公开 学生课堂行为数据集 SCB-Dataset 2 Student Classroom Behavior dataset b站&#xff1a;https://www.bilibili.com/video/BV1D34y1g76E/ arxiv: https://arxiv.org/pdf/2310.02522.pdf github: https://github.com/Whiffe/SCB-dataset 百度云&#xff1a;https://pan…

如何选择适合的发电机测试设备?

选择适合的发电机测试设备需要考虑电机的额定功率和负载需求&#xff0c;选择能够满足需求的测试设备&#xff0c;确保测试设备的功率范围覆盖发电机的额定功率&#xff0c;并有一定的余量。常见的发电机测试项目包括电压、电流、频率、功率因数、转速、温度等参数的测试&#…

PCB布线时如何保证100M以上信号的稳定性?

PCB布线时是电子工程中非常重要的环节&#xff0c;对于保证信号的稳定性和完整性至关重要&#xff0c;若电子工程师遇上100M以上信号的布线需求&#xff0c;该如何设计来保证其稳定性&#xff1f;下面或许能给你些参考。 1、选择合适的传输介质 对高速信号&#xff0c;选择合适…

基于 SaaS 搭建的党建小程序源码系统 带完整的搭建教程

随着互联网技术的发展和应用的普及&#xff0c;传统的党建模式已经难以满足现代社会的需求。为了更好地服务党员和群众&#xff0c;提高党组织的凝聚力和战斗力&#xff0c;基于 SaaS搭建的党建小程序源码系统应运而生。小程序的出现可以很好的解决大多数问题&#xff0c;方便了…

数字孪生与智慧城市:重塑未来城市生活的奇迹

今天&#xff0c;我们将探讨数字孪生和智慧城市两个颠覆性技术&#xff0c;它们正引领着未来城市生活的巨大变革。随着科技的飞速发展&#xff0c;数字孪生和智慧城市成为实现可持续发展和提升居民生活质量的关键策略。 数字孪生&#xff1a;实现现实与虚拟的完美融合 数字孪生…

AI工具在工作中的“大作用”

现如今科技的发展让我们的生活越来越便利&#xff0c;一些AI工具的出现&#xff0c;更对我们的工作有莫大的帮助。 AI工具的辅助就像给上班族提供了一种更加高级的“摸鱼方法”&#xff0c;大大提高了打工人的工作效率。如果有一种什么都能回答你&#xff0c;甚至能帮助你完成…

用例图包含关系、扩展关系、泛化关系解析(最全总结,非常详细)

一、用例图中的各种关系 a&#xff09;参与者与用例间的关联关系&#xff1a;参与者与用例之间的通信&#xff0c;也成为关联或通信关系。 b&#xff09;用例与用例之间的关系&#xff1a;包含关系&#xff08;include&#xff09;、扩展关系&#xff08;extend&#xff09;、…

智慧机场航线监测系统:提升航空运输安全与效率的新一步

在当今世界&#xff0c;空中出行已经成为越来越多人生活的一部分。人们频繁地乘坐飞机来往各地&#xff0c;全球航空旅行需求不断增长&#xff0c;航空运输业已经变得越来越复杂。在这个复杂性不断增强的行业中&#xff0c;智慧机场应用航线监测系统成为了航空领域关键的发展趋…

LeetCode2652——倍数之和

LeetCode2562 自己的解法&#xff1a; 官方给的解法&#xff08;不需要创建额外的数组&#xff0c;更为简洁&#xff0c;效率更高&#xff09;&#xff1a;

操作指南 | 如何通过Moonbeam DApp在OpenGov投票

除了Polkassembly或Polkadot.js以外&#xff0c;Moonbeam自己的DApp也可以直接参与链上治理。该界面简洁完整&#xff0c;对用户来说非常方便。 首先进入https://apps.moonbeam.network/moonbeam&#xff0c;连接你的钱包至DApp。Moonbeam DApp支持很多类型的钱包&#xff0c;…

Unity游戏开发中ngui和ugui区别与优缺点详解

Unity3D是一款跨平台的游戏开发引擎&#xff0c;它支持多种平台&#xff0c;包括PC、移动设备和主机。在Unity3D中&#xff0c;UI系统是游戏开发中非常重要的一部分&#xff0c;它负责游戏中的用户界面的显示和交互。 对惹&#xff0c;这里有一个游戏开发交流小组&#xff0c;…

rust学习特殊的地方——函数返回值

概念 Rust 中的函数定义以 fn 开始&#xff0c;后跟着函数名和一对圆括号。大括号告诉编译器函数体在哪里开始和结束。 特殊的地方——函数返回值 错误的写法 正解1 去掉分号 fn main() {let x plus_one(5);println!("The value of x is: {}", x); }fn plus_…

AI巧破网络诈骗?闭门研讨会报名丨青源Workshop第26期

青源Workshop丨No.26 AI反诈与智能风控&#xff1a;信息安全的矛与盾 AI红利接踵而至&#xff0c;安全风险如影随形。过去几年&#xff0c;人工智能技术的迅速发展催生了包括金融、电子商务、社交网络、医疗保健等众多应用场景。AI应用落地带来新安全风险&#xff0c;安全防护难…

JVS规则引擎及智能BI又更新新功能啦!赶紧来试试

规则引擎更新功能 新增: 1.复合变量新增排序、排名功能 可以按照特定的顺序对数据进行排列&#xff0c;确定规则的优先级&#xff0c;可以提高数据处理效率&#xff0c;帮助分析人员更好地了解数据分布和趋势。 2.决策流新增动态日志功能 动态日志可以记录规则执行的过程和…

品牌创意二维码营销活动:MoneyLion 在纽约全城“撒钱”,月增百万级曝光!

在2023年4月——金融知识月&#xff0c;MoneyLion 在纽约策划了一场轰动全城的“撒钱”活动&#xff01; 在开始介绍这场极具创意的活动之前&#xff0c;我们先来了解一下MoneyLion这家公司。MoneyLion 是一家私营金融科技公司&#xff0c;为消费者提供贷款、财务咨询和投资服…