Linux FrameBuffer构造图形库

来源:互联网 发布:windows如何打钢筋符号 编辑:程序博客网 时间:2024/06/06 11:45

        相信很多年前的程序员并没有想到如今有如此方便的图形系统或者说图形函数库。学过《计算机图形学》的研发人员应该知道,对于计算机绘图,就是操作一大块数据(这块数据就表示一副画面),然后把这块数据送到硬件设备里面,显示到屏幕上。计算机的处理速度很快,在一秒钟之内,操作了许多块这样的数据,并送到硬件设备里面进行显示,这样在屏幕上出现连续画面,人眼根本感觉不到操作间隔,然而大家在看电视的时候会发现,用摄像机(老式的)捕捉到的电脑屏幕,会在“有画面”与“黑屏”之间切换,这里的原因,相信学习过采样定理就会明白了。
        Linux下的FrameBuffer技术,提供图形设备(帧缓冲设备)接口和内存映射访问机制,能够让程序员直接操作前面提到的大块数据,在Linux终端下面进行绘图。这里先要区分这么一个概念,FrameBuffer更多应用于嵌入式领域,使用它来进行图形绘制更加高效,属于轻量级绘图技术。相比而言像依赖于xlib的图形函数库,更多应用于桌面系统和复杂系统,进行了多次封装和功能增加,显得庞大不易掌握。总而言之,它们的原理一样,例如使用了double buffering方法等,只是后者功能更强大,两者关系等同于C语言和C++语言。
       这里,我利用Linux FrameBuffer来构造一个轻量级的图形库,运行于S3C6410的嵌入式系统上,实现基本的绘图功能,通过这样的实践,我觉得能够使研发人员掌握计算机绘图的基本原理,同时理解Linux下mmap机制的易用性,提升设计重构能力。后期在进行维护的时候,我还会引入多任务保护,分布式同步等内容,对于未来的嵌入式系统,多任务保护和分布式计算将是重要趋势,绘图与计算可以说是一脉相承的。

注:图形库的组织和接口划分,整个结构是一种管道过滤线框架
int draw_init(),FrameBuffer的初始化,主要是用于打开/dev/fb0设备和获取显示设备参数
int get_fb(),获取/dev/fb0设备的描述符,单一模式
char *draw_mmap(int fb),将图形的帧缓存进行内存映射,便于程序员操作,由draw_init()调用
void draw_point(int x, int y, unsigned int color),在屏幕上绘制像素点
void draw_line(int x0, int y0, int x1, int y1, int color, int width),绘制线段
......<其它设计的图形接口略>
void draw_sync(),mmap的内存进行刷新操作,使得嵌入式设备的屏幕进行显示
void draw_clr(),清除屏幕操作
void draw_close(),释放绘图资源

后续就可以以此为基础,添加代码和功能。在S3C6410的终端上演示动画,以及绘制需要的图形了。

附:
mmap的作用在于将设备文件映射到内存里面,这样我们就可以用指针直接操作这块内存,赋值或者改变数值。

static int fbfd = 0;static char *fbp = NULL;static long int screensize = 0;static int x_res = 0;static int y_res = 0;static unsigned int bits_per_pixel = 8; // 默认值static unsigned int line_length = 0;int draw_init(){    struct fb_var_screeninfo vinfo;    struct fb_fix_screeninfo finfo;    fbfd = open("/dev/fb0", O_RDWR);    if (!fbfd) {        printf("Error: cannot open framebuffer device.\n");        return -1;    }    printf("The framebuffer device was opened successfully.\n");    if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo)) {        printf("Error reading fixed information.\n");        return -1;    }    if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) {        printf("Error reading variable information.\n");        return -1;    }    printf("The mem is :%d\n",finfo.smem_len);  // /dev/fb0的大小,内存的大小    printf("The line_length is :%d\n",finfo.line_length); // //屏幕上一行的点在内存中占用的空间    printf("The xres is :%d\n",vinfo.xres); //两个方向上的点数    printf("The yres is :%d\n",vinfo.yres);    printf("bits_per_pixel is :%d\n",vinfo.bits_per_pixel); // //每一点占用的内存空间    screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;    x_res = vinfo.xres;    y_res = vinfo.yres;    bits_per_pixel = vinfo.bits_per_pixel;    line_length = finfo.line_length;    printf("screensize is :%ld\n", screensize);    fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);    if ((int)fbp == -1) {        printf("Error: failed to map framebuffer device to memory.\n");        return -1;    }    printf("The framebuffer device was mapped to memory successfully.\n");    return 0;    }

详细代码请与作者联系,enjoy it!