概述
一、备注
文章中的DRM内容有一部分是下面链接的大佬整理的,还有一部分是其它来源整合,学习DRM的朋友一定要看看下面链接的文章,这个大佬写的很好
参考链接:https://blog.csdn.net/hexiaolong2009/article/details/83720940
二、DRM框架简单介绍
DRM 是linux 下的图形渲染架构(Direct Render Manager),是linux内核对显示框架进行分层设计的思想,相比于直接操作fb,drm框架提供更多的功能,包含图层合成、CMA、VSYNC等,而且架构更方便驱动人员维护和使用
framebuffer:帧缓存,帧缓存并不是指的显存上的某一块区域,而是DRM抽象出来的一个概念,用fb_id表示
plane:图层,有的硬件支持多层合成显示,Plane是连接FB与CRTC的纽带,是内存的搬运工
crtc:阴级摄像管上下文,将显存图像数据转换成硬件时序信号传输到encoder(crtc和plane是一个硬件模块?)
encoder:encoder后面接connector,比如说hdmi、mipi(connector我理解为hdmi、mipi等接口和线的抽象形式)等,但它们的时序、协议不同,所以就需要encoder(例如hdmi发送器)将crtc传输过来的信号转换成hdmi、mipi支持的协议再通过connector传输到显示器
connector:connector我理解为hdmi、mipi等接口和线的抽象形式
整个流程我理解为:
framebuffer(显存中的图像数据) -> plane(图层合并、缩放等处理)-> ctrc(将显示数据并转换成encoder可以接受的硬件信号)-> encoder(显示数据转换成不同显示输出接口的硬件信号)-> connector
三、libdrm介绍
libdrm的作用就是将内核功能封装成 一系列的open/close/ioctl 等标准接口,应用程序调用这些接口来驱动设备实现画面显示,绝大部分可以分成两类行为:Graphics Execution Manager (GEM)、Kernel Mode-Setting (KMS),gem:显存管理,如显存的分配和释放,kms:显示模式管理,如分辨率等的设置
四、libdrm安装
libdrm下载链接:https://dri.freedesktop.org/libdrm/
tar -zxvf libdrm-2.4.89.tar.gz && cd libdrm-2.4.89 && mkdir install
执行./configure -h,看一下需要加入那些配置参数,例如下图红框位置的库安装位置(--prefix,例如当前目录的install),你在什么平台上面使用(--host,例如aarch64-linux-gnu)
执行mkdir install && ./configure --prefix=/.../install/ --host=aarch64-linux-gnu && make && make install,结果如下
五、基于libdrm的简单程序编写(输出红绿蓝)
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <time.h>
#include <unistd.h>
#include "xf86drm.h"
#include "xf86drmMode.h"
#define uint32_t unsigned int
struct framebuffer{
uint32_t size;
uint32_t handle;
uint32_t fb_id;
uint32_t *vaddr;
};
static void create_fb(int fd,uint32_t width, uint32_t height, uint32_t color ,struct framebuffer *buf)
{
struct drm_mode_create_dumb create = {};
struct drm_mode_map_dumb map = {};
uint32_t i;
uint32_t fb_id;
create.width = width;
create.height = height;
create.bpp = 32;
drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &create); //创建显存,返回一个handle
drmModeAddFB(fd, create.width, create.height, 24, 32, create.pitch,create.handle, &fb_id);
map.handle = create.handle;
drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &map); //显存绑定fd,并根据handle返回offset
//通过offset找到对应的显存(framebuffer)并映射到用户空间
uint32_t *vaddr = mmap(0, create.size, PROT_READ | PROT_WRITE,MAP_SHARED, fd, map.offset);
for (i = 0; i < (create.size / 4); i++)
vaddr[i] = color;
buf->vaddr=vaddr;
buf->handle=create.handle;
buf->size=create.size;
buf->fb_id=fb_id;
return;
}
static void release_fb(int fd, struct framebuffer *buf)
{
struct drm_mode_destroy_dumb destroy = {};
destroy.handle = buf->handle;
drmModeRmFB(fd, buf->fb_id);
munmap(buf->vaddr, buf->size);
drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy);
}
int main(int argc, char **argv)
{
int fd;
struct framebuffer buf[3];
drmModeConnector *connector;
drmModeRes *resources;
uint32_t conn_id;
uint32_t crtc_id;
fd = open("/dev/dri/card0", O_RDWR | O_CLOEXEC); //打开card0,card0一般绑定HDMI和LVDS
resources = drmModeGetResources(fd); //获取drmModeRes资源,包含fb、crtc、encoder、connector等
crtc_id = resources->crtcs[0]; //获取crtc id
conn_id = resources->connectors[0]; //获取connector id
connector = drmModeGetConnector(fd, conn_id); //根据connector_id获取connector资源
printf("hdisplay:%d vdisplay:%dn",connector->modes[0].hdisplay,connector->modes[0].vdisplay);
create_fb(fd,connector->modes[0].hdisplay,connector->modes[0].vdisplay, 0xff0000, &buf[0]); //创建显存和上色
create_fb(fd,connector->modes[0].hdisplay,connector->modes[0].vdisplay, 0x00ff00, &buf[1]);
create_fb(fd,connector->modes[0].hdisplay,connector->modes[0].vdisplay, 0x0000ff, &buf[2]);
drmModeSetCrtc(fd, crtc_id, buf[0].fb_id,
0, 0, &conn_id, 1, &connector->modes[0]); //初始化和设置crtc,对应显存立即刷新
sleep(5);
drmModeSetCrtc(fd, crtc_id, buf[1].fb_id,
0, 0, &conn_id, 1, &connector->modes[0]);
sleep(5);
drmModeSetCrtc(fd, crtc_id, buf[2].fb_id,
0, 0, &conn_id, 1, &connector->modes[0]);
sleep(5);
release_fb(fd, &buf[0]);
release_fb(fd, &buf[1]);
release_fb(fd, &buf[2]);
drmModeFreeConnector(connector);
drmModeFreeResources(resources);
close(fd);
return 0;
}
六、测试
执行./drm_test,效果如下
最后
以上就是怕黑小蝴蝶为你收集整理的LIBDRM使用一、备注二、DRM框架简单介绍三、libdrm介绍四、libdrm安装五、基于libdrm的简单程序编写(输出红绿蓝)六、测试的全部内容,希望文章能够帮你解决LIBDRM使用一、备注二、DRM框架简单介绍三、libdrm介绍四、libdrm安装五、基于libdrm的简单程序编写(输出红绿蓝)六、测试所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复