Edit online

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