linux系统上drm的简单demo程序

1 篇文章 0 订阅

确保系统安装libdrm库

main.c

#include <stdio.h>
#include "drm_display.h"

int main(int argc, char **argv)
{
    int ret = 0;
    u_int32_t count = 0;
    char exit_flag = 1;

    ret = drm_dev_open();
    if (ret != 0){
        printf("drm dev open fail\n");
        return ret;
    }

    do{
        if (count%0xFF < 128)
            drm_clear_color(0xFF);
        else
            drm_clear_color(0x00);

        ++count;
        drm_display();
        if (count > 0xfff) exit_flag = 0;
    }while(exit_flag);

    drm_dev_close();
    return ret;
}

drm_display.h

#ifndef _DRM_DISPLAY_H_
#define _DRM_DISPLAY_H_

#include <sys/types.h>
#include <stdint.h>

#define DRM_DEV_PATH    "/dev/dri/card0"

struct buffer_object {
	uint32_t width;
	uint32_t height;
	uint32_t pitch;
	uint32_t handle;
	uint32_t size;
	uint32_t *vaddr;
	uint32_t fb_id;
};

int drm_dev_open();
int drm_dev_close();
void drm_display();

uint32_t drm_get_screeninfo_width();
uint32_t drm_get_screeninfo_height();

void drm_clear_color(unsigned int color);

#endif /* _DRM_DISPLAY_H_ */

drm_display.c

#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <time.h>
#include <unistd.h>
#include <signal.h>
#include <xf86drm.h>
#include <xf86drmMode.h>

#include "drm_display.h"

#define UNUSED(x)    ((void)(x))

static int drm_dev_fd = 0;
static uint8_t buf_flag = 0;
static struct buffer_object drm_buf[2];

static uint32_t drm_conn_id;
static uint32_t drm_crtc_id;
static drmEventContext drm_ev_cont = {};
static drmModeConnector *drm_conn;
static drmModeRes *drm_res;

static uint32_t *g_display_buff = NULL;

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

    create.width = bo->width;
    create.height = bo->height;
    create.bpp = 32;
    drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &create);

    bo->pitch = create.pitch;
    bo->size = create.size;
    bo->handle = create.handle;
    drmModeAddFB(fd, bo->width, bo->height, 24, create.bpp, bo->pitch,
               bo->handle, &bo->fb_id);

    map.handle = create.handle;
    drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &map);

    bo->vaddr = mmap(0, create.size, PROT_READ | PROT_WRITE,
            MAP_SHARED, fd, map.offset);

    for (i = 0; i < (bo->size / 4); i++)
        bo->vaddr[i] = color;

    return 0;
}

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

static void modeset_page_flip_handler(int fd, uint32_t frame,
                    uint32_t sec, uint32_t usec, void *data)
{
    uint32_t crtc_id = *(uint32_t *)data;

    drmModePageFlip(fd, crtc_id, drm_buf[buf_flag].fb_id, DRM_MODE_PAGE_FLIP_EVENT, data);

    UNUSED(frame); UNUSED(sec); UNUSED(usec);
}

int drm_dev_open()
{
    drm_dev_fd = open(DRM_DEV_PATH, O_RDWR | O_CLOEXEC);

    drm_res = drmModeGetResources(drm_dev_fd);
    drm_crtc_id = drm_res->crtcs[0];
    drm_conn_id = drm_res->connectors[0];

    drm_conn = drmModeGetConnector(drm_dev_fd, drm_conn_id);
    drm_buf[0].width = drm_conn->modes[0].hdisplay + 10;
    drm_buf[0].height = drm_conn->modes[0].vdisplay;
    drm_buf[1].width = drm_conn->modes[0].hdisplay + 10;
    drm_buf[1].height = drm_conn->modes[0].vdisplay;

printf("hdisplay  %d, %d\n", drm_buf[0].width, drm_buf[0].height);

    drm_ev_cont.version = DRM_EVENT_CONTEXT_VERSION;
    drm_ev_cont.page_flip_handler = modeset_page_flip_handler;

    modeset_create_fb(drm_dev_fd, &drm_buf[0], 0x000000);
    modeset_create_fb(drm_dev_fd, &drm_buf[1], 0x000000);

    drmModeSetCrtc(drm_dev_fd, drm_crtc_id, drm_buf[0].fb_id,
            0, 0, &drm_conn_id, 1, &drm_conn->modes[0]);

    drmModePageFlip(drm_dev_fd, drm_crtc_id, drm_buf[0].fb_id,
            DRM_MODE_PAGE_FLIP_EVENT, &drm_crtc_id);

printf("display_size %d \n", drm_buf[0].size);
    g_display_buff = malloc(drm_buf[0].size);
    if (NULL == g_display_buff){
        printf("malloc g_display_buff fail\n");
        return -1;
    }

    return 0;
}

int drm_dev_close()
{
    modeset_destroy_fb(drm_dev_fd, &drm_buf[1]);
    modeset_destroy_fb(drm_dev_fd, &drm_buf[0]);

    drmModeFreeConnector(drm_conn);
    drmModeFreeResources(drm_res);

    close(drm_dev_fd);
    free(g_display_buff);
    g_display_buff = NULL;
    return 0;
}

void drm_display()
{
    drmHandleEvent(drm_dev_fd, &drm_ev_cont);
    buf_flag ^= 1;
    memcpy(drm_buf[buf_flag].vaddr, g_display_buff, drm_buf[buf_flag].size);
}

void drm_clear_color(unsigned int color)
{
    memset(g_display_buff, color, drm_buf[0].size);
}

u_int32_t drm_get_screeninfo_width(){
    return drm_buf[buf_flag].width;
}

u_int32_t drm_get_screeninfo_height(){
    return drm_buf[buf_flag].height;
}

编译命令:

gcc main.c drm_display.c -ldrm -o testDRM

 

 

 

 

 

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值