LinuxDRM基本概念与使用示例(C语言)

LinuxDRM基本概念与使⽤⽰例(C语⾔)
⼀、前⾔
在本周的⼯作中为解决客户问题,查看awtk-linux-fb中的源码,其中对于⾥⾯关于DRM的内容很感兴趣,请教同事后⼜上⽹查了资料,本⽂对DRM的学习做了总结记录,并以C语⾔练习了DRM的使⽤。在此感谢回答我疑问的同事。
⼆、什么是DRM
DRM( Direct Rendering Manager)即直接渲染管理器。它是为了解决多个程序对 Video Card 资源的协同使⽤问题⽽产⽣的。它向⽤户空间提供了⼀组 API,⽤以访问操纵 GPU。
简单理解,DRM是Linux下的图形渲染架构,⽤来管理显⽰输出和分配buffer。应⽤程序可以直接操纵 DRM的 ioctl 或者是⽤framebuffer 提供的接⼝进⾏显⽰相关操作。后来封装成了 libdrm 库,让⽤户可以更加⽅便的进⾏显⽰控制。
三、DRM包含的基本概念
要弄明⽩ DRM 是怎么把⽤户的绘图输出到显⽰屏上,绕不开以下⼏个概念,具体关系如下图所⽰:
Framebuffer
CRTC
Encoder
Connector
Display Device(LCD)
防鼠网
3.1 DRM Framebuffer
它是⼀块内存区域,可以理解为⼀块画布,驱动和应⽤层都能访问它。绘制前需要将它格式化,设定绘制的⾊彩模式(例如RGB24,YUV 等)和画布的⼤⼩(分辨率)。
3.2 CRTC
阴极摄像管上下⽂。这个看名字很很难懂,但简单的来说他就是显⽰输出的上下⽂,可以理解为扫描仪。CRTC对内连接 Framebuffer 地址,对外连接 Encoder,会扫描 Framebuffer 上的内容,叠加上
Planes 的内容,最后传给Encoder。
3.3 Planes
平⾯。它和 Framebuffer ⼀样是内存地址。它的作⽤是⼲什么呢?打个⽐⽅,在电脑上,⼀边打字聊⼀边看电影,这⾥对⽴出来两个概念,打字是⽂字交互,是⼩范围更新的 Graphics 模式;看电影是全幅⾼速更新的 Video 模式,这两种模式将显卡的使⽤拉上了两个极端。
这时Planes就发挥了很好的作⽤,它给 Video 刷新提供了⾼速通道,使 Video 单独为⼀个图层,可以叠加在 Graphic 上或之下,并具有缩放等功能。
Planes 是可以有多个的,相当于图层叠加,因此扫描仪(CRTC)扫描的图像实际上往往是 Framebuffer 和 Planes 的组合(Blending)。
3.4 Encoder
编码器。它的作⽤就是将内存的 pixel 像素编码(转换)为显⽰器所需要的信号。简单理解就是,如果需要将画⾯显⽰到不同的设备(Display Device)上,需要将画⾯转化为不同的电信号,例如 DVID、VGA、YPbPr、CVBS、Mipi、eDP 等。
Encoder 和 CRTC 之间的交互就是我们所说的 ModeSetting,其中包含了前⾯提到的⾊彩模式、还有时序(Timing)等。
3.5 Connector
连接器。它常常对应于物理连接器 (例如 VGA, DVI, FPD-Link, HDMI, DisplayPort, S-Video等) ,它不是指物理线,在 DRM
中,Connector 是⼀个抽象的数据结构,代表连接的显⽰设备,从Connector中可以得到当前物理连接的输出设备相关的信息 ,例如,连接状态,EDID数据,DPMS状态、⽀持的视频模式等。
四、DRM使⽤⽰例(C语⾔)
根据上⽂,可以知道 DRM 是⼀个显⽰驱动框架,也就是把功能封装成 open/close/ioctl 等标准接⼝,应⽤程序调⽤这些接⼝来驱动设备,显⽰数据。本⽂接下来将从使⽤者的⾓度来看,验证和使⽤DRM驱动。
DRM设备节点 :DRM 驱动会在/ dev/dri 下创建3个设备节点:
card0
controlD64
renderD128
libdrm库 :DRM驱动,对⽤户空间,提供了专门的的调⽤库libdrm.so,⽤户空间通过该库可以间接的调⽤和使⽤驱动。
4.1 打开设备
/* 打开设备有专门的接⼝:drmOpen ,但此处为⽅便,使⽤open函数 */
int fd =open("/dev/dri/card0", O_RDWR | O_CLOEXEC);
if(fd <0){
ret =-errno;
fprintf(stderr,"cannot open '%s': %m\n", node);
return ret;
}
4.2 检查DRM的能⼒
DRM的能⼒通过drmGetCap接⼝获取,⽤drm_get_cap结构描述:
/** DRM_IOCTL_GET_CAP ioctl argument type */
struct drm_get_cap {
__u64 capability;
__u64 value;
};
int drmGetCap(int fd, uint64_t capability, uint64_t *value)
{
struct drm_get_cap cap;
int ret;
memclear(cap);
cap.capability = capability;
ret =drmIoctl(fd, DRM_IOCTL_GET_CAP,&cap);
if(ret)
return ret;
*value = cap.value;
return0;
}
使⽤⽰例:
uint64_t has_dumb;
if(drmGetCap(fd, DRM_CAP_DUMB_BUFFER,&has_dumb)<0||!has_dumb){
fprintf(stderr,"drm device '%s' does not support dumb buffers\n",
node);
close(fd);
return-EOPNOTSUPP;
}
4.3 检索Resource
获取Resource具体看以下函数:
drmModeResPtr drmModeGetResources(int fd)
Resource结构封装:
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, max_width;
__u32 min_height, max_height;
};
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;
使⽤⽰例:
/* retrieve resources */
int ret =drmModeGetResources(fd);
if(!res){
fprintf(stderr,"cannot retrieve DRM resources (%d): %m\n",            errno);
return-errno;
}
4.4 获取Connector
_drmModeConnector描述结构:
typedef struct _drmModeConnector {
uint32_t connector_id;
uint32_t encoder_id;/**< Encoder currently connected to */
uint32_t connector_type;
uint32_t connector_type_id;
drmModeConnection connection;
uint32_t mmWidth, mmHeight;/**< HxW in millimeters */
drmModeSubPixel subpixel;
int count_modes;
drmModeModeInfoPtr modes;
int count_props;
uint32_t *props;/**< List of property ids */
uint64_t *prop_values;/**< List of property values */
int count_encoders;
uint32_t *encoders;/**< List of encoder ids */
} drmModeConnector,*drmModeConnectorPtr;
使⽤⽰例:
drmModeConnector *conn =drmModeGetConnector(fd, res->connectors[i]);
if(!conn){
fprintf(stderr,"cannot retrieve DRM connector %u:%u (%d): %m\n",
i, res->connectors[i], errno);
continue;
}
4.5 Encoder
Encoder的结构描述:
typedef struct _drmModeEncoder {
uint32_t encoder_id;
还原剂加药装置uint32_t encoder_type;
uint32_t crtc_id;
uint32_t possible_crtcs;
uint32_t possible_clones;
} drmModeEncoder,*drmModeEncoderPtr;
使⽤⽰例:
if(conn->encoder_id)
drmModeEncoder *enc =drmModeGetEncoder(fd, conn->encoder_id);
}
三维激光扫描技术drmModeEncoderPtr drmModeGetEncoder(int fd, uint32_t encoder_id) {
struct drm_mode_get_encoder enc;
drmModeEncoderPtr r =NULL;
memclear(enc);
if(drmIoctl(fd, DRM_IOCTL_MODE_GETENCODER,&enc))
return0;
if(!(r =drmMalloc(sizeof(*r))))
return0;
r->encoder_id = der_id;
监测网站
r->crtc_id = _id;
r->encoder_type = der_type;
r->possible_crtcs = enc.possible_crtcs;
r->possible_clones = enc.possible_clones;
return r;
}
4.6 CRTC
CRTC结构描述:
struct crtc {
drmModeCrtc *crtc;
pc104主板
drmModeObjectProperties *props;
drmModePropertyRes **props_info;
drmModeModeInfo *mode;
};
typedef struct _drmModeCrtc {
uint32_t crtc_id;
uint32_t buffer_id;/**< FB id to connect to 0 = disconnect */
uint32_t x, y;/**< Position on the framebuffer */
uint32_t width, height;
int mode_valid;
drmModeModeInfo mode;
int gamma_size;/**< Number of gamma stops */
} drmModeCrtc,*drmModeCrtcPtr;
4.7 FrameBuffer
1. 创建DUMB Buffer:
ret =drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB,&creq);
if(ret <0){
fprintf(stderr,"cannot create dumb buffer (%d): %m\n",
errno);
return-errno;
}
2. 添加FrameBuffer:

本文发布于:2024-09-21 18:37:09,感谢您对本站的认可!

本文链接:https://www.17tex.com/tex/2/184036.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

上一篇:CAD接头标示
下一篇:视频接口定义
标签:连接   模式   设备   理解
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议