您尚未登录。

楼主 #1 2018-05-25 15:37:58

775624981
会员
注册时间: 2018-05-05
已发帖子: 22
积分: 17

哪位大佬用过nuc972 linux下的2D图形加速?

有没有大佬用过972的图形加速啊,这个源地址要填物理地址,但是linux应用层是虚拟地址,不能直接传进去,怎么破?

离线

#2 2018-05-25 15:45:23

晕哥
管理员
所在地: 微信 whycan_cn
注册时间: 2017-09-06
已发帖子: 9,223
积分: 9197

Re: 哪位大佬用过nuc972 linux下的2D图形加速?

官方有linux下demo,有看到吗?





离线

楼主 #3 2018-05-25 16:24:39

775624981
会员
注册时间: 2018-05-05
已发帖子: 22
积分: 17

Re: 哪位大佬用过nuc972 linux下的2D图形加速?

晕哥 说:

官方有linux下demo,有看到吗?

那个我知道啊,那个demo是先用970_mem映射了一段地址,但是假如我想在lvgl里用,比如fbdev_flush函数里,那个color的指针是个应用层的虚拟地址....

离线

#4 2018-05-25 16:32:43

晕哥
管理员
所在地: 微信 whycan_cn
注册时间: 2017-09-06
已发帖子: 9,223
积分: 9197

Re: 哪位大佬用过nuc972 linux下的2D图形加速?

对,我记得就是这么干的,开辟一块内存,然后有两个地址,一个给驱动用,一个给应用,调用接口可以完成 旋转,矩形填充,拷贝等2d加速。

你的问题我有空看下代码,看看如何做比较合适。





离线

楼主 #5 2018-05-25 16:42:14

775624981
会员
注册时间: 2018-05-05
已发帖子: 22
积分: 17

Re: 哪位大佬用过nuc972 linux下的2D图形加速?

晕哥 说:

对,我记得就是这么干的,开辟一块内存,然后有两个地址,一个给驱动用,一个给应用,调用接口可以完成 旋转,矩形填充,拷贝等2d加速。

你的问题我有空看下代码,看看如何做比较合适。

这个思路的话貌似只能先开辟内存,然后应用用到的内存都是在这段内存里才能取到物理地址...

离线

#6 2018-05-25 16:43:49

晕哥
管理员
所在地: 微信 whycan_cn
注册时间: 2017-09-06
已发帖子: 9,223
积分: 9197

Re: 哪位大佬用过nuc972 linux下的2D图形加速?

对,你的目的是2d加速,他能完成这个功能,只是实现有点烧脑而已。





离线

#7 2018-05-25 18:00:54

晕哥
管理员
所在地: 微信 whycan_cn
注册时间: 2017-09-06
已发帖子: 9,223
积分: 9197

Re: 哪位大佬用过nuc972 linux下的2D图形加速?

2d_demo.h

/* demos/2d/2d_demo.h
 *
 * Copyright (c) 2015 Nuvoton technology corporation
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
*/
#ifndef GE2D_DEMO_H
#define GE2D_DEMO_H

typedef enum
{
	G2D_BLACK = 0, G2D_RED = 1, G2D_GREEN = 2, G2D_BLUE = 3, G2D_WHITE = 4, 
	G2D_YELLOW = 5, G2D_CYAN = 6, G2D_MAGENTA = 7
} G2D_COLOR;

/* LCD Display Description */
struct nuc970fb_display {
	/* LCD Image type */
	unsigned type;

	/* LCD Screen Size */
	unsigned short width;
	unsigned short height;
    
	/* LCD Screen Info */
	unsigned short xres;
	unsigned short yres;
	unsigned short bpp;

	unsigned long pixclock;
	unsigned short left_margin;
	unsigned short right_margin;
	unsigned short hsync_len;
	unsigned short upper_margin;
	unsigned short lower_margin;
	unsigned short vsync_len;

	/* hardware special register value */
	unsigned int dccs;
	unsigned int devctl;
	unsigned int fbctrl;
	unsigned int scale;
    unsigned int phy_addr;
};

typedef enum
{
	G2D_SCALE_DOWN, G2D_SCALE_UP
} G2D_SCALE_MODE;

typedef struct
{
    unsigned int	src_base_addr;			//Base address of the source image
	unsigned int	src_full_width;			//source image full width
	unsigned int	src_full_height;		//source image full height
	unsigned int	src_start_x;			//coordinate start x of source image
	unsigned int	src_start_y;			//coordinate start y of source image
	unsigned int	src_work_width;			//source image width for work
	unsigned int    src_work_height;		//source image height for work
    unsigned int    src_colormode;

	unsigned int	dst_base_addr;			//Base address of the destination image	
	unsigned int	dst_full_width;			//destination screen full width
	unsigned int	dst_full_height;		//destination screen full width
	unsigned int	dst_start_x;			//coordinate start x of destination screen
	unsigned int	dst_start_y;			//coordinate start y of destination screen
	unsigned int	dst_work_width;			//destination screen width for work
	unsigned int    dst_work_height;		//destination screen height for work
    unsigned int    dst_colormode;

	// Coordinate (X, Y) of clipping window
	unsigned int    cw_x1, cw_y1;
	unsigned int    cw_x2, cw_y2;
    
    // Line address
    unsigned int    line_x1, line_y1;
	unsigned int    line_x2, line_y2;
    
	unsigned char   color_val[8];

	// Alpha blending
    unsigned int	alpha_mode;			//true : enable, false : disable
	unsigned int	alpha_val;
    
    // Transparent
	unsigned int	color_key_mode;			//true : enable, false : disable
	unsigned int	color_key_val;			//transparent color value    
    
	unsigned char   bpp_src;
    unsigned char   rop;        // rop code
    unsigned char   rotate;     // rotate option
    
    // Scale up/down
    unsigned char   scale_mode;
    unsigned int    scale_vfn, scale_vfm, scale_hfn, scale_hfm;
}nuc970_g2d_params;

struct nuc970_mem_alloc {
	int		size;
	unsigned int	vir_addr;
	unsigned int	phy_addr;
    unsigned int	kvir_addr;
};

typedef enum
{
	ROT_R_45=1, ROT_L_45, ROT_L_90, ROT_UP_DOWN, ROT_R_90, ROT_180
} G2D_ROT_DEG;

typedef struct 
{
    char *file_name;
    int width;
    int height;
} image_info_t;

int                         g_mem_fd;
struct nuc970fb_display     g_working_fb;

#define NUC970FB_GET_FB_INFO		    _IOW('F', 203, struct nuc970fb_display)

#define NUC970_GE2D_START_BITBLT		_IO('G',0)
#define NUC970_GE2D_START_BITBLT_ROP	_IO('G',1)
#define NUC970_GE2D_FILL_RECTANGLE	    _IO('G',2)
#define NUC970_GE2D_ROTATION		    _IO('G',3)
#define NUC970_GE2D_LINE		        _IO('G',4)
#define NUC970_GE2D_STRETCH		        _IO('G',5)

#define NUC970_MEM_ALLOC		        _IOWR('M', 310,	struct nuc970_mem_alloc)
#define NUC970_MEM_FREE		            _IOWR('M', 311, struct nuc970_mem_alloc)
                        
#define RANDOM_PATH "/dev/urandom"

#endif

2d_demo.c

/* demos/2d/2d_demo.c
 *
 * Copyright (c) 2015 Nuvoton technology corporation
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <ctype.h>
#include <errno.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/poll.h>
#include <pthread.h>
#include <linux/fb.h>
#include <sched.h>
#include <unistd.h>
#include <linux/vt.h>
#include <linux/ioctl.h>

#include "2d_demo.h"

#define SRC_IMAGE_FILE_NAME_0 "/mnt/sda1/image/image_800x480_rgb888_1.dat"
#define SRC_IMAGE_FILE_NAME_1 "/mnt/sda1/image/image_320x240_rgb888_1.dat"
#define SRC_IMAGE_FILE_NAME_2 "/mnt/sda1/image/image_100x100_rgb888_1.dat"

image_info_t image_info[3] = {
                                { SRC_IMAGE_FILE_NAME_0, 800, 480},
                                { SRC_IMAGE_FILE_NAME_1, 320, 240},
                                { SRC_IMAGE_FILE_NAME_2, 100, 100},
                             };
                             
unsigned short get_random_num(unsigned short mask)
{
    unsigned char buf[2];
    unsigned short v;
    FILE *fin;
        
    if ((fin = fopen(RANDOM_PATH, "r")) == NULL) {
            fprintf(stderr, "%s: unable to open file\n", RANDOM_PATH);
            return EXIT_FAILURE;
    }
    if (fread(buf, 1, sizeof buf, fin) != sizeof buf) {
            fprintf(stderr, "%s: not enough bytes (expected %u)\n",
                    RANDOM_PATH, (unsigned) sizeof buf);
            return EXIT_FAILURE;
    }
    fclose(fin);
    
    v = buf[0] | (buf[1] << 8UL);
     
    return (v%mask); 
}

static void print_menu(void)
{
    printf("\n===== NUC970 2D test Application =======\n");
    printf("=                                        =\n");
    printf("=  r.    reset frame buffer              =\n");
    printf("=  q.    exit                            =\n");
    printf("=  1.    bitblt                          =\n");
    printf("=  2.    bitblt with rop                 =\n");
    printf("=  3.    fill rectangle                  =\n");
    printf("=  4.    rotate                          =\n");
    printf("=  5.    line                            =\n");
    printf("=  6.    scale up/down                   =\n");
    printf("=                                        =\n");
    printf("=========================================\n");
    printf("Select number -->: ");
}
                        
int file_open_and_mmap ( char *file_name, char **mmap_addr, int *size )
{
    int     in_fd;

    struct stat    s;

    in_fd = open(file_name, O_RDONLY);
    if (in_fd < 0) {
        printf("input file open error\n");
        return -1;
    }

    // get input file size
    fstat(in_fd, &s);
    *size = s.st_size;

    // mapping input file to memory
    *mmap_addr = (char *) mmap(0, *size, PROT_READ, MAP_SHARED, in_fd, 0);
    if(mmap_addr == NULL) {
        printf("input file memory mapping failed\n");
        return -1;
    }

    return in_fd;
}

void select_image(int image, unsigned int copyto)
{
    char *image_ptr;
    int image_fd;    
    int file_size;
    
    printf("copy %dx%d image to off-screen buffer ...\n", image_info[image].width, image_info[image].height);
    
    if  ( (image_fd = file_open_and_mmap ( image_info[image].file_name, &image_ptr, &file_size ) ) < 0 )
        return;    
    memcpy((unsigned char *)copyto , image_ptr, file_size); 
    close(image_fd);
    munmap(image_ptr, file_size);
}
                   
int main(int argc, char *argv[])
{
    int fb_fd, ge2d_fd, ret, strip;
    int i, key;
    unsigned char *pVideoBuffer;
    struct fb_fix_screeninfo finfo;
    struct fb_var_screeninfo vinfo;
    nuc970_g2d_params params;
    struct nuc970_mem_alloc mem_alloc;
    
    fb_fd = open("/dev/fb0", O_RDWR);
    if (fb_fd == -1) {
            printf("Cannot open fb0!\n");
            return -1;
    }
    
    ge2d_fd = open("/dev/ge2d", O_RDWR);
    if (ge2d_fd == -1) {
            printf("Cannot open ge2d!\n");
            return -1;
    }
    
    if (ioctl(fb_fd, FBIOGET_FSCREENINFO, &finfo) < 0) {
        perror("ioctl(FBIOGET_FSCREENINFO)");
        return -1;
    }
    
    if (ioctl(fb_fd, FBIOGET_VSCREENINFO, &vinfo) < 0) {
        perror("ioctl(FBIOGET_VSCREENINFO)");
        return -1;
    }
    
    switch(vinfo.bits_per_pixel)
    {
        case 16:
            strip = 2;
            break;
        
        case 24:
        case 32:
            strip = 4;
            break;
    }
    pVideoBuffer = mmap(NULL, vinfo.xres * vinfo.yres * strip, PROT_READ|PROT_WRITE, MAP_SHARED, fb_fd, 0);
    
    if (pVideoBuffer == MAP_FAILED) {
            printf("mmap() failed\n");
            exit(0);
    }
    
    g_mem_fd = open("/dev/nuc970-mem", O_RDWR);
    if (g_mem_fd == -1) {
        printf("Cannot open mem!\n");
        return -1;
    }
    
    mem_alloc.size = vinfo.xres * vinfo.yres * strip;
    if ( ioctl(g_mem_fd, NUC970_MEM_ALLOC, &mem_alloc) )
    {
        printf("OOPS!!!! line=%d, size=%d\n", __LINE__, (int)mem_alloc.size );
        return -1;
     }
    printf("Memory ==> vir_addr = 0x%08x, phy_addr = 0x%08x\n", 
            mem_alloc.vir_addr, mem_alloc.phy_addr);
    
    while(1)
    {
        print_menu();
        key = getc(stdin);
        
        switch(key)
        {
            case 'r':
                memset(pVideoBuffer, 0x0, vinfo.xres * vinfo.yres * 4);
                break;
                
            case 'q':
                goto exit;
                
            case '1':   //bitblt
                select_image(0, mem_alloc.vir_addr);
                params.src_start_x = 0;
                params.src_start_y = 0;
                params.src_work_width = image_info[0].width;
                params.src_work_height = image_info[0].height;
                params.dst_start_x = 0;
                params.dst_start_y = 0;
                params.bpp_src = vinfo.bits_per_pixel;                
                params.src_full_width = image_info[0].width;
                params.dst_full_width = vinfo.xres;
                params.src_base_addr = mem_alloc.phy_addr;
                params.dst_base_addr = finfo.smem_start;
                
                ioctl(ge2d_fd, NUC970_GE2D_START_BITBLT, &params);
                break;

            case '2':   //bitblt with rop
                select_image(1, mem_alloc.vir_addr);
                params.src_start_x = 0;
                params.src_start_y = 0;
                params.src_work_width = image_info[1].width;
                params.src_work_height = image_info[1].height;
                params.dst_start_x = 0;
                params.dst_start_y = 0;
                params.bpp_src = vinfo.bits_per_pixel;                
                params.src_full_width = image_info[1].width;
                params.dst_full_width = vinfo.xres;
                params.src_base_addr = mem_alloc.phy_addr;
                params.dst_base_addr = finfo.smem_start;
                
                for(i=1;i<10;i++) {
                    params.rop = i;                
                    ioctl(ge2d_fd, NUC970_GE2D_START_BITBLT_ROP, &params);
                    
                    printf("Press a key to continue ...\n");
                    getc(stdin);
                    memset(pVideoBuffer, 0x0, vinfo.xres * vinfo.yres * 4);
                }
                break;
            
            case '3':   //fill rectangle
                for(i=0;i<10;i++) {
                    params.dst_start_x = (unsigned int)get_random_num(700);
                    params.dst_start_y = (unsigned int)get_random_num(350);
                    params.dst_work_width =  (unsigned int)get_random_num(500);
                    params.dst_work_height =  (unsigned int)get_random_num(200);
                    
                    if (params.dst_work_width + params.dst_start_x > vinfo.xres)
                        params.dst_work_width = vinfo.xres - params.dst_start_x;
                    if (params.dst_work_width == 0)
                        params.dst_work_width = 1;
                    
                    if (params.dst_work_height + params.dst_start_y > vinfo.yres)
                        params.dst_work_height = vinfo.yres - params.dst_start_y;
                    if (params.dst_work_height == 0)
                        params.dst_work_height = 1;
                    
                    params.bpp_src = vinfo.bits_per_pixel;                
                    params.dst_full_width = vinfo.xres;
                    
                    params.color_val[G2D_RED] = get_random_num(255);
                    params.color_val[G2D_GREEN] = get_random_num(255);
                    params.color_val[G2D_BLUE] = get_random_num(255);
                    
                    params.src_base_addr = mem_alloc.phy_addr;
                    params.dst_base_addr = finfo.smem_start;
                         
                    ioctl(ge2d_fd, NUC970_GE2D_FILL_RECTANGLE, &params);                 
                }
                break;
            
            case '4':   //rotation
                select_image(2, mem_alloc.vir_addr);
                for(i=1;i<8;i++) {
                    params.src_start_x = 0;
                    params.src_start_y = 0;
                    params.src_work_width = image_info[2].width;
                    params.src_work_height = image_info[2].height;
                    params.dst_start_x = 300;
                    params.dst_start_y = 200;
                    params.bpp_src = vinfo.bits_per_pixel;                
                    params.src_full_width = image_info[2].width;
                    params.dst_full_width = vinfo.xres;
                    
                    params.rotate = i;
                                        
                    params.src_base_addr = mem_alloc.phy_addr;
                    params.dst_base_addr = finfo.smem_start;
                         
                    ioctl(ge2d_fd, NUC970_GE2D_ROTATION, &params);
                    sleep(1);
                }               
                break;  
            
            case '5':   //draw line
                params.bpp_src = vinfo.bits_per_pixel;                
                params.dst_full_width = vinfo.xres;
                params.dst_full_height = vinfo.yres;
                params.src_base_addr = mem_alloc.phy_addr;
                params.dst_base_addr = finfo.smem_start;

                params.line_x1 = 0;
                params.line_y1 = 0;
                params.line_x2 = vinfo.xres-1;
                params.line_y2 = 0+1;
                
                params.color_val[G2D_RED] = get_random_num(255);
                params.color_val[G2D_GREEN] = get_random_num(255);
                params.color_val[G2D_BLUE] = get_random_num(255);
               
                for (i=0; i<80; i++) {                        
                    ioctl(ge2d_fd, NUC970_GE2D_LINE, &params);
                    params.line_x1 += 4;
                    params.line_y2 += 3;
                }

                params.color_val[G2D_RED] = get_random_num(255);
                params.color_val[G2D_GREEN] = get_random_num(255);
                params.color_val[G2D_BLUE] = get_random_num(255);
                
                params.line_x1 = vinfo.xres-1;
                params.line_y1 = 0;
                params.line_x2 = vinfo.xres-1;
                params.line_y2 = vinfo.yres-1;
                for (i=0; i<80; i++) {
                    ioctl(ge2d_fd, NUC970_GE2D_LINE, &params);
                    params.line_y1 += 3;
                    params.line_x2 -= 4;
                }

                params.color_val[G2D_RED] = get_random_num(255);
                params.color_val[G2D_GREEN] = get_random_num(255);
                params.color_val[G2D_BLUE] = get_random_num(255);
                
                params.line_x1 = vinfo.xres-1;
                params.line_y1 = vinfo.yres-1;
                params.line_x2 = 0;
                params.line_y2 = vinfo.yres;
                for (i=0; i<80; i++) {
                    ioctl(ge2d_fd, NUC970_GE2D_LINE, &params);
                    params.line_x1 -= 4;
                    params.line_y2 -= 3;
                }

                params.color_val[G2D_RED] = get_random_num(255);
                params.color_val[G2D_GREEN] = get_random_num(255);
                params.color_val[G2D_BLUE] = get_random_num(255);
                params.line_x1 = 0;
                params.line_y1 = vinfo.yres-1;
                params.line_x2 = 0;
                params.line_y2 = 0;
                for (i=0; i<80; i++) {
                    ioctl(ge2d_fd, NUC970_GE2D_LINE, &params);
                    params.line_y1 -= 3;
                    params.line_x2 += 4;
                }
                break;
                
            case '6':   //scale up/down
                select_image(1, mem_alloc.vir_addr);
                params.src_start_x = 0;
                params.src_start_y = 0;
                params.src_work_width = image_info[1].width;
                params.src_work_height = image_info[1].height;
                params.dst_start_x = 240;
                params.dst_start_y = 100;
                params.bpp_src = vinfo.bits_per_pixel;                
                params.src_full_width = image_info[1].width;
                params.dst_full_width = vinfo.xres;
                params.src_base_addr = mem_alloc.phy_addr;
                params.dst_base_addr = finfo.smem_start;
                
                for(i=2;i<10;i+=2)
                {
                    params.scale_mode = G2D_SCALE_DOWN;
                    params.scale_vfn = 1;
                    params.scale_vfm = i;
                    params.scale_hfn = 1;
                    params.scale_hfm = i;                
                    ioctl(ge2d_fd, NUC970_GE2D_STRETCH, &params);
                    sleep(1);
                }
                
                memset(pVideoBuffer, 0x0, vinfo.xres * vinfo.yres * 4);
                
                for(i=2;i<10;i+=2)
                {
                    params.scale_mode = G2D_SCALE_UP;
                    params.scale_vfn = 1;
                    params.scale_vfm = i;
                    params.scale_hfn = 1;
                    params.scale_hfm = i;                
                    ioctl(ge2d_fd, NUC970_GE2D_STRETCH, &params);
                    sleep(1);
                }
                break;
                
            default:
                printf("no exist input command, please enter the command number \n");
                break;
        }
        getc(stdin);
    }

exit:
    munmap(pVideoBuffer, vinfo.xres * vinfo.yres * strip);
    if ( ioctl(g_mem_fd, NUC970_MEM_FREE, &mem_alloc) )
        return;
    close(g_mem_fd);
    
    printf("exit!!\n");
}




离线

楼主 #8 2018-05-26 09:50:09

775624981
会员
注册时间: 2018-05-05
已发帖子: 22
积分: 17

Re: 哪位大佬用过nuc972 linux下的2D图形加速?

晕哥 说:

2d_demo.h

/* demos/2d/2d_demo.h
 *
 * Copyright (c) 2015 Nuvoton technology corporation
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
*/
#ifndef GE2D_DEMO_H
#define GE2D_DEMO_H

typedef enum
{
	G2D_BLACK = 0, G2D_RED = 1, G2D_GREEN = 2, G2D_BLUE = 3, G2D_WHITE = 4, 
	G2D_YELLOW = 5, G2D_CYAN = 6, G2D_MAGENTA = 7
} G2D_COLOR;

/* LCD Display Description */
struct nuc970fb_display {
	/* LCD Image type */
	unsigned type;

	/* LCD Screen Size */
	unsigned short width;
	unsigned short height;
    
	/* LCD Screen Info */
	unsigned short xres;
	unsigned short yres;
	unsigned short bpp;

	unsigned long pixclock;
	unsigned short left_margin;
	unsigned short right_margin;
	unsigned short hsync_len;
	unsigned short upper_margin;
	unsigned short lower_margin;
	unsigned short vsync_len;

	/* hardware special register value */
	unsigned int dccs;
	unsigned int devctl;
	unsigned int fbctrl;
	unsigned int scale;
    unsigned int phy_addr;
};

typedef enum
{
	G2D_SCALE_DOWN, G2D_SCALE_UP
} G2D_SCALE_MODE;

typedef struct
{
    unsigned int	src_base_addr;			//Base address of the source image
	unsigned int	src_full_width;			//source image full width
	unsigned int	src_full_height;		//source image full height
	unsigned int	src_start_x;			//coordinate start x of source image
	unsigned int	src_start_y;			//coordinate start y of source image
	unsigned int	src_work_width;			//source image width for work
	unsigned int    src_work_height;		//source image height for work
    unsigned int    src_colormode;

	unsigned int	dst_base_addr;			//Base address of the destination image	
	unsigned int	dst_full_width;			//destination screen full width
	unsigned int	dst_full_height;		//destination screen full width
	unsigned int	dst_start_x;			//coordinate start x of destination screen
	unsigned int	dst_start_y;			//coordinate start y of destination screen
	unsigned int	dst_work_width;			//destination screen width for work
	unsigned int    dst_work_height;		//destination screen height for work
    unsigned int    dst_colormode;

	// Coordinate (X, Y) of clipping window
	unsigned int    cw_x1, cw_y1;
	unsigned int    cw_x2, cw_y2;
    
    // Line address
    unsigned int    line_x1, line_y1;
	unsigned int    line_x2, line_y2;
    
	unsigned char   color_val[8];

	// Alpha blending
    unsigned int	alpha_mode;			//true : enable, false : disable
	unsigned int	alpha_val;
    
    // Transparent
	unsigned int	color_key_mode;			//true : enable, false : disable
	unsigned int	color_key_val;			//transparent color value    
    
	unsigned char   bpp_src;
    unsigned char   rop;        // rop code
    unsigned char   rotate;     // rotate option
    
    // Scale up/down
    unsigned char   scale_mode;
    unsigned int    scale_vfn, scale_vfm, scale_hfn, scale_hfm;
}nuc970_g2d_params;

struct nuc970_mem_alloc {
	int		size;
	unsigned int	vir_addr;
	unsigned int	phy_addr;
    unsigned int	kvir_addr;
};

typedef enum
{
	ROT_R_45=1, ROT_L_45, ROT_L_90, ROT_UP_DOWN, ROT_R_90, ROT_180
} G2D_ROT_DEG;

typedef struct 
{
    char *file_name;
    int width;
    int height;
} image_info_t;

int                         g_mem_fd;
struct nuc970fb_display     g_working_fb;

#define NUC970FB_GET_FB_INFO		    _IOW('F', 203, struct nuc970fb_display)

#define NUC970_GE2D_START_BITBLT		_IO('G',0)
#define NUC970_GE2D_START_BITBLT_ROP	_IO('G',1)
#define NUC970_GE2D_FILL_RECTANGLE	    _IO('G',2)
#define NUC970_GE2D_ROTATION		    _IO('G',3)
#define NUC970_GE2D_LINE		        _IO('G',4)
#define NUC970_GE2D_STRETCH		        _IO('G',5)

#define NUC970_MEM_ALLOC		        _IOWR('M', 310,	struct nuc970_mem_alloc)
#define NUC970_MEM_FREE		            _IOWR('M', 311, struct nuc970_mem_alloc)
                        
#define RANDOM_PATH "/dev/urandom"

#endif

2d_demo.c

/* demos/2d/2d_demo.c
 *
 * Copyright (c) 2015 Nuvoton technology corporation
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <ctype.h>
#include <errno.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/poll.h>
#include <pthread.h>
#include <linux/fb.h>
#include <sched.h>
#include <unistd.h>
#include <linux/vt.h>
#include <linux/ioctl.h>

#include "2d_demo.h"

#define SRC_IMAGE_FILE_NAME_0 "/mnt/sda1/image/image_800x480_rgb888_1.dat"
#define SRC_IMAGE_FILE_NAME_1 "/mnt/sda1/image/image_320x240_rgb888_1.dat"
#define SRC_IMAGE_FILE_NAME_2 "/mnt/sda1/image/image_100x100_rgb888_1.dat"

image_info_t image_info[3] = {
                                { SRC_IMAGE_FILE_NAME_0, 800, 480},
                                { SRC_IMAGE_FILE_NAME_1, 320, 240},
                                { SRC_IMAGE_FILE_NAME_2, 100, 100},
                             };
                             
unsigned short get_random_num(unsigned short mask)
{
    unsigned char buf[2];
    unsigned short v;
    FILE *fin;
        
    if ((fin = fopen(RANDOM_PATH, "r")) == NULL) {
            fprintf(stderr, "%s: unable to open file\n", RANDOM_PATH);
            return EXIT_FAILURE;
    }
    if (fread(buf, 1, sizeof buf, fin) != sizeof buf) {
            fprintf(stderr, "%s: not enough bytes (expected %u)\n",
                    RANDOM_PATH, (unsigned) sizeof buf);
            return EXIT_FAILURE;
    }
    fclose(fin);
    
    v = buf[0] | (buf[1] << 8UL);
     
    return (v%mask); 
}

static void print_menu(void)
{
    printf("\n===== NUC970 2D test Application =======\n");
    printf("=                                        =\n");
    printf("=  r.    reset frame buffer              =\n");
    printf("=  q.    exit                            =\n");
    printf("=  1.    bitblt                          =\n");
    printf("=  2.    bitblt with rop                 =\n");
    printf("=  3.    fill rectangle                  =\n");
    printf("=  4.    rotate                          =\n");
    printf("=  5.    line                            =\n");
    printf("=  6.    scale up/down                   =\n");
    printf("=                                        =\n");
    printf("=========================================\n");
    printf("Select number -->: ");
}
                        
int file_open_and_mmap ( char *file_name, char **mmap_addr, int *size )
{
    int     in_fd;

    struct stat    s;

    in_fd = open(file_name, O_RDONLY);
    if (in_fd < 0) {
        printf("input file open error\n");
        return -1;
    }

    // get input file size
    fstat(in_fd, &s);
    *size = s.st_size;

    // mapping input file to memory
    *mmap_addr = (char *) mmap(0, *size, PROT_READ, MAP_SHARED, in_fd, 0);
    if(mmap_addr == NULL) {
        printf("input file memory mapping failed\n");
        return -1;
    }

    return in_fd;
}

void select_image(int image, unsigned int copyto)
{
    char *image_ptr;
    int image_fd;    
    int file_size;
    
    printf("copy %dx%d image to off-screen buffer ...\n", image_info[image].width, image_info[image].height);
    
    if  ( (image_fd = file_open_and_mmap ( image_info[image].file_name, &image_ptr, &file_size ) ) < 0 )
        return;    
    memcpy((unsigned char *)copyto , image_ptr, file_size); 
    close(image_fd);
    munmap(image_ptr, file_size);
}
                   
int main(int argc, char *argv[])
{
    int fb_fd, ge2d_fd, ret, strip;
    int i, key;
    unsigned char *pVideoBuffer;
    struct fb_fix_screeninfo finfo;
    struct fb_var_screeninfo vinfo;
    nuc970_g2d_params params;
    struct nuc970_mem_alloc mem_alloc;
    
    fb_fd = open("/dev/fb0", O_RDWR);
    if (fb_fd == -1) {
            printf("Cannot open fb0!\n");
            return -1;
    }
    
    ge2d_fd = open("/dev/ge2d", O_RDWR);
    if (ge2d_fd == -1) {
            printf("Cannot open ge2d!\n");
            return -1;
    }
    
    if (ioctl(fb_fd, FBIOGET_FSCREENINFO, &finfo) < 0) {
        perror("ioctl(FBIOGET_FSCREENINFO)");
        return -1;
    }
    
    if (ioctl(fb_fd, FBIOGET_VSCREENINFO, &vinfo) < 0) {
        perror("ioctl(FBIOGET_VSCREENINFO)");
        return -1;
    }
    
    switch(vinfo.bits_per_pixel)
    {
        case 16:
            strip = 2;
            break;
        
        case 24:
        case 32:
            strip = 4;
            break;
    }
    pVideoBuffer = mmap(NULL, vinfo.xres * vinfo.yres * strip, PROT_READ|PROT_WRITE, MAP_SHARED, fb_fd, 0);
    
    if (pVideoBuffer == MAP_FAILED) {
            printf("mmap() failed\n");
            exit(0);
    }
    
    g_mem_fd = open("/dev/nuc970-mem", O_RDWR);
    if (g_mem_fd == -1) {
        printf("Cannot open mem!\n");
        return -1;
    }
    
    mem_alloc.size = vinfo.xres * vinfo.yres * strip;
    if ( ioctl(g_mem_fd, NUC970_MEM_ALLOC, &mem_alloc) )
    {
        printf("OOPS!!!! line=%d, size=%d\n", __LINE__, (int)mem_alloc.size );
        return -1;
     }
    printf("Memory ==> vir_addr = 0x%08x, phy_addr = 0x%08x\n", 
            mem_alloc.vir_addr, mem_alloc.phy_addr);
    
    while(1)
    {
        print_menu();
        key = getc(stdin);
        
        switch(key)
        {
            case 'r':
                memset(pVideoBuffer, 0x0, vinfo.xres * vinfo.yres * 4);
                break;
                
            case 'q':
                goto exit;
                
            case '1':   //bitblt
                select_image(0, mem_alloc.vir_addr);
                params.src_start_x = 0;
                params.src_start_y = 0;
                params.src_work_width = image_info[0].width;
                params.src_work_height = image_info[0].height;
                params.dst_start_x = 0;
                params.dst_start_y = 0;
                params.bpp_src = vinfo.bits_per_pixel;                
                params.src_full_width = image_info[0].width;
                params.dst_full_width = vinfo.xres;
                params.src_base_addr = mem_alloc.phy_addr;
                params.dst_base_addr = finfo.smem_start;
                
                ioctl(ge2d_fd, NUC970_GE2D_START_BITBLT, &params);
                break;

            case '2':   //bitblt with rop
                select_image(1, mem_alloc.vir_addr);
                params.src_start_x = 0;
                params.src_start_y = 0;
                params.src_work_width = image_info[1].width;
                params.src_work_height = image_info[1].height;
                params.dst_start_x = 0;
                params.dst_start_y = 0;
                params.bpp_src = vinfo.bits_per_pixel;                
                params.src_full_width = image_info[1].width;
                params.dst_full_width = vinfo.xres;
                params.src_base_addr = mem_alloc.phy_addr;
                params.dst_base_addr = finfo.smem_start;
                
                for(i=1;i<10;i++) {
                    params.rop = i;                
                    ioctl(ge2d_fd, NUC970_GE2D_START_BITBLT_ROP, &params);
                    
                    printf("Press a key to continue ...\n");
                    getc(stdin);
                    memset(pVideoBuffer, 0x0, vinfo.xres * vinfo.yres * 4);
                }
                break;
            
            case '3':   //fill rectangle
                for(i=0;i<10;i++) {
                    params.dst_start_x = (unsigned int)get_random_num(700);
                    params.dst_start_y = (unsigned int)get_random_num(350);
                    params.dst_work_width =  (unsigned int)get_random_num(500);
                    params.dst_work_height =  (unsigned int)get_random_num(200);
                    
                    if (params.dst_work_width + params.dst_start_x > vinfo.xres)
                        params.dst_work_width = vinfo.xres - params.dst_start_x;
                    if (params.dst_work_width == 0)
                        params.dst_work_width = 1;
                    
                    if (params.dst_work_height + params.dst_start_y > vinfo.yres)
                        params.dst_work_height = vinfo.yres - params.dst_start_y;
                    if (params.dst_work_height == 0)
                        params.dst_work_height = 1;
                    
                    params.bpp_src = vinfo.bits_per_pixel;                
                    params.dst_full_width = vinfo.xres;
                    
                    params.color_val[G2D_RED] = get_random_num(255);
                    params.color_val[G2D_GREEN] = get_random_num(255);
                    params.color_val[G2D_BLUE] = get_random_num(255);
                    
                    params.src_base_addr = mem_alloc.phy_addr;
                    params.dst_base_addr = finfo.smem_start;
                         
                    ioctl(ge2d_fd, NUC970_GE2D_FILL_RECTANGLE, &params);                 
                }
                break;
            
            case '4':   //rotation
                select_image(2, mem_alloc.vir_addr);
                for(i=1;i<8;i++) {
                    params.src_start_x = 0;
                    params.src_start_y = 0;
                    params.src_work_width = image_info[2].width;
                    params.src_work_height = image_info[2].height;
                    params.dst_start_x = 300;
                    params.dst_start_y = 200;
                    params.bpp_src = vinfo.bits_per_pixel;                
                    params.src_full_width = image_info[2].width;
                    params.dst_full_width = vinfo.xres;
                    
                    params.rotate = i;
                                        
                    params.src_base_addr = mem_alloc.phy_addr;
                    params.dst_base_addr = finfo.smem_start;
                         
                    ioctl(ge2d_fd, NUC970_GE2D_ROTATION, &params);
                    sleep(1);
                }               
                break;  
            
            case '5':   //draw line
                params.bpp_src = vinfo.bits_per_pixel;                
                params.dst_full_width = vinfo.xres;
                params.dst_full_height = vinfo.yres;
                params.src_base_addr = mem_alloc.phy_addr;
                params.dst_base_addr = finfo.smem_start;

                params.line_x1 = 0;
                params.line_y1 = 0;
                params.line_x2 = vinfo.xres-1;
                params.line_y2 = 0+1;
                
                params.color_val[G2D_RED] = get_random_num(255);
                params.color_val[G2D_GREEN] = get_random_num(255);
                params.color_val[G2D_BLUE] = get_random_num(255);
               
                for (i=0; i<80; i++) {                        
                    ioctl(ge2d_fd, NUC970_GE2D_LINE, &params);
                    params.line_x1 += 4;
                    params.line_y2 += 3;
                }

                params.color_val[G2D_RED] = get_random_num(255);
                params.color_val[G2D_GREEN] = get_random_num(255);
                params.color_val[G2D_BLUE] = get_random_num(255);
                
                params.line_x1 = vinfo.xres-1;
                params.line_y1 = 0;
                params.line_x2 = vinfo.xres-1;
                params.line_y2 = vinfo.yres-1;
                for (i=0; i<80; i++) {
                    ioctl(ge2d_fd, NUC970_GE2D_LINE, &params);
                    params.line_y1 += 3;
                    params.line_x2 -= 4;
                }

                params.color_val[G2D_RED] = get_random_num(255);
                params.color_val[G2D_GREEN] = get_random_num(255);
                params.color_val[G2D_BLUE] = get_random_num(255);
                
                params.line_x1 = vinfo.xres-1;
                params.line_y1 = vinfo.yres-1;
                params.line_x2 = 0;
                params.line_y2 = vinfo.yres;
                for (i=0; i<80; i++) {
                    ioctl(ge2d_fd, NUC970_GE2D_LINE, &params);
                    params.line_x1 -= 4;
                    params.line_y2 -= 3;
                }

                params.color_val[G2D_RED] = get_random_num(255);
                params.color_val[G2D_GREEN] = get_random_num(255);
                params.color_val[G2D_BLUE] = get_random_num(255);
                params.line_x1 = 0;
                params.line_y1 = vinfo.yres-1;
                params.line_x2 = 0;
                params.line_y2 = 0;
                for (i=0; i<80; i++) {
                    ioctl(ge2d_fd, NUC970_GE2D_LINE, &params);
                    params.line_y1 -= 3;
                    params.line_x2 += 4;
                }
                break;
                
            case '6':   //scale up/down
                select_image(1, mem_alloc.vir_addr);
                params.src_start_x = 0;
                params.src_start_y = 0;
                params.src_work_width = image_info[1].width;
                params.src_work_height = image_info[1].height;
                params.dst_start_x = 240;
                params.dst_start_y = 100;
                params.bpp_src = vinfo.bits_per_pixel;                
                params.src_full_width = image_info[1].width;
                params.dst_full_width = vinfo.xres;
                params.src_base_addr = mem_alloc.phy_addr;
                params.dst_base_addr = finfo.smem_start;
                
                for(i=2;i<10;i+=2)
                {
                    params.scale_mode = G2D_SCALE_DOWN;
                    params.scale_vfn = 1;
                    params.scale_vfm = i;
                    params.scale_hfn = 1;
                    params.scale_hfm = i;                
                    ioctl(ge2d_fd, NUC970_GE2D_STRETCH, &params);
                    sleep(1);
                }
                
                memset(pVideoBuffer, 0x0, vinfo.xres * vinfo.yres * 4);
                
                for(i=2;i<10;i+=2)
                {
                    params.scale_mode = G2D_SCALE_UP;
                    params.scale_vfn = 1;
                    params.scale_vfm = i;
                    params.scale_hfn = 1;
                    params.scale_hfm = i;                
                    ioctl(ge2d_fd, NUC970_GE2D_STRETCH, &params);
                    sleep(1);
                }
                break;
                
            default:
                printf("no exist input command, please enter the command number \n");
                break;
        }
        getc(stdin);
    }

exit:
    munmap(pVideoBuffer, vinfo.xres * vinfo.yres * strip);
    if ( ioctl(g_mem_fd, NUC970_MEM_FREE, &mem_alloc) )
        return;
    close(g_mem_fd);
    
    printf("exit!!\n");
}

这个demo是固定存储到flash的图片数据,用mem映射物理内存到应用层了,但是假如要实现程序中用一个随机的颜色数组刷屏,就不知道怎么得到物理地址了
比如 void fbdev_flush(int32_t x1, int32_t y1, int32_t x2, int32_t y2, const lv_color_t * color_p)
这个color_p,它并不是预先用mem映射到的地址
假如先用mem,得到一个虚拟地址v_addr和物理地址p_addr,再把color_p的内容copy到v_addr,倒是可以实现,但是这样就多了一步memcpy,那ge2d也就没有意义了,是我想的不对吗

离线

#9 2018-05-26 10:06:30

晕哥
管理员
所在地: 微信 whycan_cn
注册时间: 2017-09-06
已发帖子: 9,223
积分: 9197

Re: 哪位大佬用过nuc972 linux下的2D图形加速?

memcpy效率还行,而且可以用dma实现,2d加速还是有意义的,如果动用cpu去填充一个矩形,或者画一条直线,
绝对比memcpy要更耗时。





离线

楼主 #10 2018-05-26 10:24:59

775624981
会员
注册时间: 2018-05-05
已发帖子: 22
积分: 17

Re: 哪位大佬用过nuc972 linux下的2D图形加速?

晕哥 说:

memcpy效率还行,而且可以用dma实现,2d加速还是有意义的,如果动用cpu去填充一个矩形,或者画一条直线,
绝对比memcpy要更耗时。

矩形填充和画线当然没问题,毕竟不需要物理地址,BLT就蛋疼了,除了memcpy,目前想不出什么办法了

离线

#11 2019-01-19 17:24:31

jw__liu
会员
注册时间: 2019-01-18
已发帖子: 40
积分: 40

Re: 哪位大佬用过nuc972 linux下的2D图形加速?

mark

离线

页脚

工信部备案:粤ICP备20025096号 Powered by FluxBB

感谢为中文互联网持续输出优质内容的各位老铁们。 QQ: 516333132, 微信(wechat): whycan_cn (哇酷网/挖坑网/填坑网) service@whycan.cn