Drm 单个buff显示

这章介绍drm的部分的函数和结构体,实现单个frambuffer的显示

drm buff相关结构体

struct buffer object

struct buffer_object {unsigned int width;unsigned int height;unsigned int pitch;     //图片每一行数据所占字节数 例800*1280 rgb  ->800*3unsigned int handle;    //gem 缓冲区fdunsigned int size;unsigned int *vaddr;unsigned int fb_id;        //framebuffer创建的bufid
};

struct drm_mode_create_dumb

struct drm_mode_create_dumb {//user fill in__u32 height;__u32 width;__u32 bpp;       //像素位深__u32 flags;  //current unused//kernel return fill in__u32 handle;    //gem 缓冲区fd__u32 pitch; //图片每一行数据所占字节数 例800*1280 rgb  ->800*3__u64 size;     //(height * pitch + width) * bpp / 4
};

struct drm_mode_map_dumb

struct drm_mode_map_dumb {__u32 handle;      //申请的gem handle__u32 pad;           //unused__u64 offset;       //用于mmap的偏移大小
};

通过ioctl来创建获取dumb buf

/* 创建一个dumb buffer
ioctl can be used to create a dumb buffer. The kernel will return a 32bit handle
that can be used to manage the buffer with the DRM API. You can create framebuffers with
*/
DRM_IOCTL_MODE_CREATE_DUMB
/*获取dumb内存映射偏移值
ioctl requests the DRM subsystem to prepare the buffer for memory-mapping and returns a
fake-offset that can be used with*/
DRM_IOCTL_MODE_MAP_DUMB

drmModeRes

typedef struct _drmModeRes {int count_fbs;       //当前申请的framebuffer的数量uint32_t *fbs;     int count_crtcs;    //可用的crtcs配置uint32_t *crtcs;int count_connectors;   //可用的连接器connectorsuint32_t *connectors;int count_encoders;      //可用的编码器encoders uint32_t *encoders;uint32_t min_width, max_width;uint32_t min_height, max_height;
} drmModeRes, *drmModeResPtr;

drm相关操作函数

drmSetClientCap

drm设置客户端属性

/** DRM_IOCTL_SET_CLIENT_CAP ioctl argument type */
struct drm_set_client_cap {__u64 capability;__u64 value;
};
/*** DRM_CLIENT_CAP_STEREO_3D** if set to 1, the DRM core will expose the stereo 3D capabilities of the* monitor by advertising the supported 3D layouts in the flags of struct* drm_mode_modeinfo.*/
#define DRM_CLIENT_CAP_STEREO_3D    1/*** DRM_CLIENT_CAP_UNIVERSAL_PLANES** If set to 1, the DRM core will expose all planes (overlay, primary, and* cursor) to userspace.*/
#define DRM_CLIENT_CAP_UNIVERSAL_PLANES  2/*** DRM_CLIENT_CAP_ATOMIC** If set to 1, the DRM core will expose atomic properties to userspace*/
#define DRM_CLIENT_CAP_ATOMIC   3int drmSetClientCap(int fd, uint64_t capability, uint64_t value)
{struct drm_set_client_cap cap;memclear(cap);cap.capability = capability;cap.value = value;return drmIoctl(fd, DRM_IOCTL_SET_CLIENT_CAP, &cap);
}

drmModeGetResources

获取card的所有资源信息

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

drmModeFreeResources

void drmModeFreeResources(drmModeResPtr ptr)
{if (!ptr)return;drmFree(ptr->fbs);drmFree(ptr->crtcs);drmFree(ptr->connectors);drmFree(ptr->encoders);drmFree(ptr);
}

drmModeGetConnector

获取card的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;
}

drmModeFreeConnector

释放connector

void drmModeFreeConnector(drmModeConnectorPtr ptr)
{if (!ptr)return;drmFree(ptr->encoders);drmFree(ptr->prop_values);drmFree(ptr->props);drmFree(ptr->modes);drmFree(ptr);
}

drmModeObjectGetProperties

获取connector dpms (Display Power Manage System)属性

drmModeObjectPropertiesPtr drmModeObjectGetProperties(int fd,uint32_t object_id,uint32_t object_type)
{struct drm_mode_obj_get_properties properties;drmModeObjectPropertiesPtr ret = NULL;uint32_t count;retry:memclear(properties);properties.obj_id = object_id;properties.obj_type = object_type;if (drmIoctl(fd, DRM_IOCTL_MODE_OBJ_GETPROPERTIES, &properties))return 0;count = properties.count_props;if (count) {properties.props_ptr = VOID2U64(drmMalloc(count *sizeof(uint32_t)));if (!properties.props_ptr)goto err_allocs;properties.prop_values_ptr = VOID2U64(drmMalloc(count *sizeof(uint64_t)));if (!properties.prop_values_ptr)goto err_allocs;}if (drmIoctl(fd, DRM_IOCTL_MODE_OBJ_GETPROPERTIES, &properties))goto err_allocs;if (count < properties.count_props) {drmFree(U642VOID(properties.props_ptr));drmFree(U642VOID(properties.prop_values_ptr));goto retry;}count = properties.count_props;ret = drmMalloc(sizeof(*ret));if (!ret)goto err_allocs;ret->count_props = count;ret->props = drmAllocCpy(U642VOID(properties.props_ptr),count, sizeof(uint32_t));ret->prop_values = drmAllocCpy(U642VOID(properties.prop_values_ptr),count, sizeof(uint64_t));if (ret->count_props && (!ret->props || !ret->prop_values)) {drmFree(ret->props);drmFree(ret->prop_values);drmFree(ret);ret = NULL;}err_allocs:drmFree(U642VOID(properties.props_ptr));drmFree(U642VOID(properties.prop_values_ptr));return ret;
}

drmModeGetEncoder

获取Encoder

drmModeEncoderPtr drmModeGetEncoder(int fd, uint32_t encoder_id)
{struct drm_mode_get_encoder enc;drmModeEncoderPtr r = NULL;memclear(enc);enc.encoder_id = encoder_id;if (drmIoctl(fd, DRM_IOCTL_MODE_GETENCODER, &enc))return 0;if (!(r = drmMalloc(sizeof(*r))))return 0;r->encoder_id = enc.encoder_id;r->crtc_id = enc.crtc_id;r->encoder_type = enc.encoder_type;r->possible_crtcs = enc.possible_crtcs;r->possible_clones = enc.possible_clones;return r;
}

drmModeGetCrtc

Retrive information about the ctrt crtcId

drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId)
{struct drm_mode_crtc crtc;drmModeCrtcPtr r;memclear(crtc);crtc.crtc_id = crtcId;if (drmIoctl(fd, DRM_IOCTL_MODE_GETCRTC, &crtc))return 0;/** return*/if (!(r = drmMalloc(sizeof(*r))))return 0;r->crtc_id         = crtc.crtc_id;r->x               = crtc.x;r->y               = crtc.y;r->mode_valid      = crtc.mode_valid;if (r->mode_valid) {memcpy(&r->mode, &crtc.mode, sizeof(struct drm_mode_modeinfo));r->width = crtc.mode.hdisplay;r->height = crtc.mode.vdisplay;}r->buffer_id       = crtc.fb_id;r->gamma_size      = crtc.gamma_size;return r;
}

drmModeAddFB

Creates a new framebuffer with an buffer object as its scanout buffer

创建一个具有buffer对象的framebuffer作为扫描buffer

int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth,uint8_t bpp, uint32_t pitch, uint32_t bo_handle,uint32_t *buf_id)
{struct drm_mode_fb_cmd f;int ret;memclear(f);f.width  = width;f.height = height;f.pitch  = pitch;f.bpp    = bpp;f.depth  = depth;f.handle = bo_handle;if ((ret = DRM_IOCTL(fd, DRM_IOCTL_MODE_ADDFB, &f)))return ret;*buf_id = f.fb_id;return 0;
}

drmModeRmFB

释放创建的framebuffer

int drmModeRmFB(int fd, uint32_t bufferId)
{return DRM_IOCTL(fd, DRM_IOCTL_MODE_RMFB, &bufferId);
}

drmModeSetCrtc

Set the mode on a crtc crtcId with the given mode modeId.

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

例程

伪代码

1.open card

2.获取card的connector和encoder id

3.创建dumb buffer ,从内存中获取dumb 映射的偏移值,mmap申请,申请framebuffer 填充dumb buffer

4.销毁资源

代码

#include <stdio.h>
#include <errno.h>
#include "xf86drmMode.h"
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <string.h>#define DRM_CARD    "/dev/dri/card0"
#define check_ptr(ptr) do{ \if(ptr == NULL) { \printf("ptr is NULL\n"); \return -1; \} \
} while (0)#define drm_print(fmt, args...) \
do \
{ \printf("func:%s line:%d "#fmt"\n",  __FUNCTION__, __LINE__, ##args); \
}while (0)typedef struct _buffer_object {unsigned int width;unsigned int height;unsigned int pitch;unsigned int handle;unsigned int size;unsigned char *vaddr;unsigned int fb_id;
}buffer_object;typedef struct  _drm_ctx{int fd;    buffer_object buf;unsigned int conector_id;unsigned int crtc_id;unsigned int encoder_id;
}drm_ctx;drm_ctx gdrm_var;static int creat_fb(int fd, buffer_object *bo)
{struct drm_mode_create_dumb creq;struct drm_mode_map_dumb mreq;int ret;creq.width = bo->width;creq.height = bo->height;creq.bpp = 32;ret = ioctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &creq);if(ret != 0){drm_print("ioctl creat dumb fail\n");return -1;}bo->pitch = creq.pitch;bo->handle = creq.handle;bo->size = creq.size;drmModeAddFB(fd, bo->width, bo->height, 24, 32, bo->pitch, bo->handle, &bo->fb_id);mreq.handle = bo->handle;ret = ioctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &mreq);if(ret != 0){drm_print("ioctl mmap dumb fail\n");return -1;}/* perform actual memory mapping */bo->vaddr = mmap(0, creq.size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, mreq.offset);check_ptr(bo->vaddr);//使用crtc驱动connectormemset(bo->vaddr, 0xff, bo->size);return 0;
}static int destroy_fb(int fd, buffer_object *bo)
{int ret;struct drm_mode_destroy_dumb dreq;drmModeRmFB(fd, bo->fb_id);dreq.handle = bo->handle;ret = ioctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dreq);if(ret != 0){drm_print("ioctl destory dumb fail\n");return -1;}munmap(bo->vaddr, bo->size);
}int main(int argc, char *argv[])
{//open carddrmModeResPtr   resptr;drmModeConnectorPtr conptr;int ret;unsigned int fb;gdrm_var.fd = open(DRM_CARD, O_RDWR);if(gdrm_var.fd < 0){perror("open card fail\n");return -1;}drm_print("fd%d\n", gdrm_var.fd);//获取card resource,include crtc connector encoder planeresptr = drmModeGetResources(gdrm_var.fd);check_ptr(resptr);gdrm_var.crtc_id = resptr->crtcs[0];gdrm_var.conector_id = resptr->connectors[0];drm_print("crtc id:%d conector_id %d", gdrm_var.crtc_id, gdrm_var.conector_id);//printf("%s %d crtc_id:%d con_id:%d\n", resptr->count_crtcs, resptr->count_connectors);//select which connector usedconptr = drmModeGetConnector(gdrm_var.fd, gdrm_var.conector_id);check_ptr(conptr);gdrm_var.buf.width = conptr->modes[0].hdisplay;gdrm_var.buf.height = conptr->modes[0].vdisplay;drm_print("%d %d", gdrm_var.buf.width, gdrm_var.buf.height);//create framebuffer, fill dumb buffercreat_fb(gdrm_var.fd, &gdrm_var.buf);drmModeSetCrtc(gdrm_var.fd, gdrm_var.crtc_id, gdrm_var.buf.fb_id,0, 0, &gdrm_var.conector_id, 1, &conptr->modes[0]);//destory dumb buffersleep(5);destroy_fb(gdrm_var.fd, &gdrm_var.buf);drmModeFreeConnector(conptr);drmModeFreeResources(resptr);close(gdrm_var.fd);
}

drm单个framebuffer显示相关推荐

  1. framebuffer显示JPEG图片

    framebuffer显示JPEG图片 2011-05-03 20:14:45 分类: 嵌入式 转自http://www.linuxsense.org/archives/281.html http:/ ...

  2. FRAMEBUFFER 显示原理及RGB显示

    Framebuffer是把内存中视频数据输出的设备驱动程序,Linux的framebuffer是独立的硬件抽象层,它可以把显示设备抽象为帧缓冲区,并把自己当作显示内存的一个映像,开发者可以通过这个映像 ...

  3. linux frame buffer 显示图片 没有颜色,新路程----linux framebuffer显示图片c程序

    #include #include #include #include #include #include #include #include #include #include //14byte文件 ...

  4. 金蝶K/3插件 - 单个单据显示

    'BillTYPE 单据类型 'lBillID 单据id '使用单据类型和单据ID显示一个单据 Private Sub viewBill(ByVal BillTYPE As Long, ByVal l ...

  5. Word2019单个页面显示多个文件

    最近使用word,每打开一个新文件就有一个新页面,想像WPS一样通过上方的选项卡快速切换文件,但是查了很久没有合适的解决方法,遂摸索出一点替代的技巧 1.视图->切换窗口 2.右键点击切换窗口, ...

  6. Framebuffer、DRM、EXA和Mesa简介

    1. Framebuffer Framebuffer驱动提供基本的显示,framebuffer驱动操作的硬件就是一个显示控制器和帧缓存(一片位于系统主存或者显卡显存).Framebuffer驱动向应用 ...

  7. linux显示子系统-framebuffer架构分析

    目录 简介 驱动层 时序数据流 架构 应用层 实例 fb架构优劣势 参考文件 简介 FrameBuffer,帧缓冲,简称fb,也叫显存,下文以fb代表framebuffer.该子系统是内核针对显示系统 ...

  8. 【转】自上而下解读Android显示流程

    同济大学 计算机系统结构硕士 107 人赞同了该文章 当我们点击"知乎"这个应用后,它是怎么在屏幕上显示出来的? 这个问题困扰我很久了,当我刚接触显示的时候,大约是十年前的事情了, ...

  9. linux drm 内存管理,Linux RK3399 DRM 框架及代码流程 · Younix’s Studio

    8种机械键盘轴体对比 本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选? RK3399 OS: Android 6.0 Kernel: 4.4 Version: v2017.04 DRM 简介 ...

最新文章

  1. 别了比特币,BCH将领导加密货币!
  2. VIM 多行注释与取消
  3. 静态链接和动态链接优缺点
  4. CUDA系列学习(一)An Introduction to GPU and CUDA
  5. centos7开发java体验_centos7之Java开发环境构建
  6. 解决NHibernate 中与 SQL2005 关键字有冲突的问题
  7. javascript 盒子模型
  8. Shell 的简单常用语法
  9. 最小生成树——安慰奶牛(蓝桥杯试题集)
  10. 不要给我说什么底层原理_连集合底层实现原理都不知道,你敢说 Redis 用的很溜?...
  11. 各种系统扫描磁带驱动器的操作方法
  12. 云中漫步-柴米油盐之上
  13. android动态壁纸--美女报时
  14. 用php做滚动,用PHP+java实现自动新闻滚动窗口
  15. java 7新特性-TWR(Try-with-resources)
  16. 哪些企业可以做知识产权贯标,你不得不了解的事!
  17. HP-UX Samba服务配置手册
  18. 渗透测试实战3——bulldog2靶机入侵
  19. vba的change事件
  20. Android自定义控件之短信验证码自动填充

热门文章

  1. 对接京东获取任务工单接口jingdong.homefw.task.search,附接口字段详细说明,数据库设计,Java实现
  2. 【学习笔记】《卓有成效的管理者》 第四章 如何发挥人的长处
  3. 修改http默认的80端口为其它端口
  4. rap2一键部署 (包括RAP2-DELOS与RAP2-DOLORES)
  5. java算法:逻辑回归和线性回归
  6. VC单位线程是如何处理消息的.txt
  7. shiro的基本认识
  8. CrowdHuman数据集介绍
  9. nodejs 运行在tomcat_nodejs和tomcat的区别是什么?
  10. Guava - 拯救垃圾代码,写出优雅高效,效率提升N倍