libdrm(二)显示PNG图片

#ifndef __libdrmToDMD_H__ 
#define __libdrmToDMD_H__ 

#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 <png.h>
#include "xf86drm.h"
#include "xf86drmMode.h"


#define uint32_t unsigned int


struct framebuffer{
    uint32_t size;
    uint32_t handle;
    uint32_t fb_id;
    char *vaddr;
};


struct drmbuffer{
    drmModeConnector *connector;
    drmModeRes *resources;
    png_structp png_ptr;
    uint32_t conn_id;
    uint32_t crtc_id;
    struct framebuffer buf;
};

struct drmbuffer get_drm_info(int fd);
int read_png_framebuffer(char *fileName, struct framebuffer *png);
void release_fb(int fd, struct framebuffer *buf);

int libdrminit();


#endif

#include "libdrmToDMD.h"


int read_png_framebuffer(char *fileName, struct framebuffer *framebuf)
{
    FILE* file = fopen(fileName, "rb");    //打开的文件名
    if(file == NULL )
        return -1;

    png_bytepp row_pointers;
    png_infop info_ptr;
    png_structp png_ptr;
    int width;
    int height;

    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);   //创建初始化libpng库结构体
    info_ptr = png_create_info_struct(png_ptr);                         //创建图片信息结构体

    if(png_ptr == NULL || info_ptr == NULL )
        return -1;
    if(setjmp(png_jmpbuf(png_ptr)))                            //设置错误的返回点
       return -1;

    png_init_io(png_ptr, file);         //把文件加载到libpng库结构体中
    png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND, 0);        //读文件内容到info_ptr中

    width = png_get_image_width(png_ptr, info_ptr);
    height = png_get_image_height(png_ptr, info_ptr);      //通过png库中的api获取图片的宽度和高度


    row_pointers = png_get_rows(png_ptr, info_ptr);

    int temp = (3 * width);

    for(int i = 0; i < height; i++)
    {
       for(int j = 0; j < temp; j += 3)
       {
           framebuf->vaddr[i*temp+j+0] = row_pointers[i][j]; // red
           framebuf->vaddr[i*temp+j+1] = row_pointers[i][j+1]; // green
           framebuf->vaddr[i*temp+j+2] = row_pointers[i][j+2];  // blue
       }
    }

    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);


    fclose(file);

    return 0;
}



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

struct drmbuffer get_drm_info(int fd)
{
    uint32_t fb_id;
    struct drm_mode_create_dumb create = {};
    struct drm_mode_map_dumb map = {};
    struct drmbuffer drm= {};

    drm.resources = drmModeGetResources(fd);	//获取drmModeRes资源,包含fb、crtc、encoder、connector等
    drm.crtc_id = drm.resources->crtcs[0];			//获取crtc id
    drm.conn_id = drm.resources->connectors[0];		//获取connector id

    drm.connector = drmModeGetConnector(fd, drm.conn_id);	//根据connector_id获取connector资源

    printf("hdisplay:%d vdisplay:%d\n",drm.connector->modes[0].hdisplay,drm.connector->modes[0].vdisplay);

    create.width =drm.connector->modes[0].hdisplay;
    create.height = drm.connector->modes[0].vdisplay;
    create.bpp = 24;
    drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &create);	//创建显存,返回一个handle

    drmModeAddFB(fd, create.width, create.height, 24, 24, create.pitch,create.handle, &fb_id);

    map.handle = create.handle;
    drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &map);	//显存绑定fd,并根据handle返回offset

    //通过offset找到对应的显存(framebuffer)并映射到用户空间
    drm.buf.vaddr = mmap(0, create.size, PROT_READ | PROT_WRITE,MAP_SHARED, fd, map.offset);

    printf("size:%d width:%d height:%d pitch:%d handle:%d offset:%d\n",create.size, create.width,create.height,create.pitch,create.handle,map.offset);

    drm.buf.handle=create.handle;
    drm.buf.size=create.size;
    drm.buf.fb_id=fb_id;

    return drm;

}

int libdrminit()
{
    int fd = open("/dev/dri/card0", O_RDWR | O_CLOEXEC);	//打开card0,card0一般绑定HDMI和LVDS

    struct drmbuffer drm= get_drm_info(fd);

    printf("hdisplay:%d vdisplay:%d\n",drm.connector->modes[0].hdisplay,drm.connector->modes[0].vdisplay);

    char PicPath4[100] = "/home/linaro/build-T2D3-QTforARM-Debug/bmp_3840";
    char PicPath5[100] ;

    for (int i = 2;i<10;i++)
    {
        char s[10]="/slice";
        char d[10]=".PNG";
        char temp1[10];
        sprintf(temp1,"%d",i);
        memset(PicPath5,0,100);
        strcpy(PicPath5,PicPath4);
        strcat(s,temp1);
        strcat(s,d);
        strcat(PicPath5,s);
        printf("<<<  PicPath5:%s\n",PicPath5);

        read_png_framebuffer(PicPath5,&drm.buf);

        printf("<<%d\n",i);

        drmModeSetCrtc(fd, drm.crtc_id, drm.buf.fb_id,0, 0, &drm.conn_id, 1, &drm.connector->modes[0]);	//初始化和设置crtc,对应显存立即刷新
        sleep(5);
    }
    release_fb(fd, & drm.buf);

    drmModeFreeConnector(drm.connector);
    drmModeFreeResources(drm.resources);

    close(fd);

	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值