Demo
Demo 代码见 test-ge/ge_bitblt.c,如下:
#include <signal.h> #include <sys/time.h> #include <linux/fb.h> #include <artinchip/sample_base.h> #include <video/artinchip_fb.h> #include <linux/dma-buf.h> #include <linux/dma-heap.h> #include "mpp_ge.h" #define FB_DEV "/dev/fb0" #define DMA_HEAP_DEV "/dev/dma_heap/reserved" static int g_screen_w = 0; static int g_screen_h = 0; static int g_fb_fd = 0; static int g_fb_len = 0; static int g_fb_stride = 0; static unsigned int g_fb_format = 0; static unsigned int g_fb_phy = 0; unsigned char *g_fb_buf = NULL; static const char sopts[] = "w:h:f:i:u"; static const struct option lopts[] = { {"width", required_argument, NULL, 'w'}, {"height", required_argument, NULL, 'h'}, {"format", required_argument, NULL, 'f'}, {"input", required_argument, NULL, 'i'}, {"usage", no_argument, NULL, 'u'}, }; static int fb_open(void) { struct fb_fix_screeninfo fix; struct fb_var_screeninfo var; struct aicfb_layer_data layer; g_fb_fd = open(FB_DEV, O_RDWR); if (g_fb_fd == -1) { ERR("open %s", FB_DEV); return -1; } if (ioctl(g_fb_fd, FBIOGET_FSCREENINFO, &fix) < 0) { ERR("ioctl FBIOGET_FSCREENINFO"); close(g_fb_fd); return -1; } if (ioctl(g_fb_fd, FBIOGET_VSCREENINFO, &var) < 0) { ERR("ioctl FBIOGET_VSCREENINFO"); close(g_fb_fd); return -1; } if(ioctl(g_fb_fd, AICFB_GET_FB_LAYER_CONFIG, &layer) < 0) { ERR("ioctl FBIOGET_VSCREENINFO"); close(g_fb_fd); return -1; } g_screen_w = var.xres; g_screen_h = var.yres; g_fb_len = fix.smem_len; g_fb_phy = fix.smem_start; g_fb_stride = layer.buf.stride[0]; g_fb_format = layer.buf.format; g_fb_buf = mmap(NULL, g_fb_len, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, g_fb_fd, 0); if (g_fb_buf == (unsigned char *)-1) { ERR("mmap framebuffer"); close(g_fb_fd); g_fb_fd = -1; g_fb_buf = NULL; return -1; } DBG("screen_w = %d, screen_h = %d, stride = %d, format = %d\n", var.xres, var.yres, g_fb_stride, g_fb_format); return 0; } static void fb_close(void) { if (!g_fb_buf) { munmap(g_fb_buf, g_fb_len); } if (g_fb_fd > 0) close(g_fb_fd); } static void usage(char *app) { printf("Usage: %s [Options], built on %s %s\n", app, __DATE__, __TIME__); printf("\t-w, --width image width\n"); printf("\t-h, --height image height\n"); printf("\t-i, --input need an argb8888 bmp \n"); printf("\t-u, --usage\n\n"); printf("Example: %s -w 480 -h 320 -i my.bmp\n", app); } static int dmabuf_request_one(int fd, int len) { int ret; struct dma_heap_allocation_data data = {0}; if (len < 0) { ERR("Invalid len %d\n", len); return -1; } data.fd = 0; data.len = len; data.fd_flags = O_RDWR; data.heap_flags = 0; ret = ioctl(fd, DMA_HEAP_IOCTL_ALLOC, &data); if (ret < 0) { ERR("ioctl() failed! errno: %d[%s]\n", errno, strerror(errno)); return -1; } DBG("Get dma_heap fd: %d\n", data.fd); return data.fd; } static int draw_src_dmabuf(int dmabuf_fd, int fd, int len) { unsigned char * buf = NULL; int ret = 0; buf = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, dmabuf_fd, 0); if (buf == MAP_FAILED) { ERR("mmap() failed! errno: %d[%s]\n", errno, strerror(errno)); return -1; } ret = read(fd, buf, len); if (ret != len) { ERR("read(%d) return %d. errno: %d[%s]\n", len, ret, errno, strerror(errno)); return -1; } munmap(buf, len); return 0; } int main(int argc, char **argv) { struct mpp_ge *ge = NULL; int ret = 0; int src_fd = -1; int src_dmabuf_fd = -1; int heap_fd = -1; int fsize = 0; int width = 176; int height = 144; struct ge_bitblt blt = {0}; while ((ret = getopt_long(argc, argv, sopts, lopts, NULL)) != -1) { switch (ret) { case 'u': usage(argv[0]); goto EXIT; case 'w': width = str2int(optarg); continue; case 'h': height = str2int(optarg); continue; case 'i': src_fd = open(optarg, O_RDONLY); if (src_fd < 0) { ERR("Failed to open %s. errno: %d[%s]\n", optarg, errno, strerror(errno)); return -1; } fsize = lseek(src_fd, 0, SEEK_END); lseek(src_fd, 54, SEEK_SET); break; default: ERR("Invalid parameter: %#x\n", ret); goto EXIT; } } ge = mpp_ge_open(); if (!ge) { ERR("open ge device\n"); exit(1); } if (fb_open()) { fb_close(); mpp_ge_close(ge); ERR("fb_open\n"); exit(1); } heap_fd = open(DMA_HEAP_DEV, O_RDWR); if (heap_fd < 0) { ERR("Failed to open %s, errno: %d[%s]\n", DMA_HEAP_DEV, errno, strerror(errno)); goto EXIT; } src_dmabuf_fd = dmabuf_request_one(heap_fd, fsize); if (src_dmabuf_fd < 0) { ERR("Failed to request dmabuf\n"); goto EXIT; } draw_src_dmabuf(src_dmabuf_fd, src_fd, fsize - 54); mpp_ge_add_dmabuf(ge, src_dmabuf_fd); /* source buffer */ blt.src_buf.buf_type = MPP_DMA_BUF_FD; blt.src_buf.fd[0] = src_dmabuf_fd; blt.src_buf.stride[0] = width * 4; blt.src_buf.size.width = width; blt.src_buf.size.height = height; blt.src_buf.format = MPP_FMT_ARGB_8888; blt.src_buf.crop_en = 0; /* dstination buffer */ blt.dst_buf.buf_type = MPP_PHY_ADDR; blt.dst_buf.phy_addr[0] = g_fb_phy; blt.dst_buf.stride[0] = g_fb_stride; blt.dst_buf.size.width = g_screen_w; blt.dst_buf.size.height = g_screen_h; blt.dst_buf.format = g_fb_format; blt.ctrl.flags = GE_FLIP_H; blt.dst_buf.crop_en = 1; blt.dst_buf.crop.x = 0; blt.dst_buf.crop.y = 0; blt.dst_buf.crop.width = width; blt.dst_buf.crop.height = height; ret = mpp_ge_bitblt(ge, &blt); DBG("bitblt task:%d\n", ret); ret = mpp_ge_emit(ge); DBG("emit task:%d\n", ret); ret = mpp_ge_sync(ge); DBG("sync task:%d\n", ret); return ret; EXIT: if (heap_fd > 0) close(heap_fd); if (ge) mpp_ge_close(ge); fb_close(); return -1; }