有没有大佬用过972的图形加速啊,这个源地址要填物理地址,但是linux应用层是虚拟地址,不能直接传进去,怎么破?
离线
官方有linux下demo,有看到吗?
那个我知道啊,那个demo是先用970_mem映射了一段地址,但是假如我想在lvgl里用,比如fbdev_flush函数里,那个color的指针是个应用层的虚拟地址....
离线
对,我记得就是这么干的,开辟一块内存,然后有两个地址,一个给驱动用,一个给应用,调用接口可以完成 旋转,矩形填充,拷贝等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, ¶ms); 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, ¶ms); 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, ¶ms); } 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, ¶ms); 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, ¶ms); 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, ¶ms); 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, ¶ms); 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, ¶ms); 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, ¶ms); 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, ¶ms); 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也就没有意义了,是我想的不对吗
离线
memcpy效率还行,而且可以用dma实现,2d加速还是有意义的,如果动用cpu去填充一个矩形,或者画一条直线,
绝对比memcpy要更耗时。
矩形填充和画线当然没问题,毕竟不需要物理地址,BLT就蛋疼了,除了memcpy,目前想不出什么办法了
离线