Linux FrameBuffer分析之编写基于FrameBuffer接口的应用程序

作者:刘昊昱

博客:http://blog.csdn.net/liuhaoyutz

测试环境:Ubuntu 12.04终端模式

在网上找到一个很不错的介绍FrameBuffer相关知识的帖子,原帖网址如下:http://bbs.chinaunix.net/thread-1932291-1-1.html,现把其中测试FrameBuffer的应用程序代码转帖过来,方便分析学习:

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <linux/kd.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <string.h>
#include <errno.h>

struct fb_var_screeninfo vinfo;
struct fb_fix_screeninfo finfo;
char *frameBuffer = 0;

//打印fb驱动中fix结构信息,注:在fb驱动加载后,fix结构不可被修改。
void
printFixedInfo ()
{
   printf ("Fixed screen info:\n"
                        "\tid: %s\n"
                        "\tsmem_start:0x%lx\n"
                        "\tsmem_len:%d\n"
                        "\ttype:%d\n"
                        "\ttype_aux:%d\n"
                        "\tvisual:%d\n"
                        "\txpanstep:%d\n"
                        "\typanstep:%d\n"
                        "\tywrapstep:%d\n"
                        "\tline_length: %d\n"
                        "\tmmio_start:0x%lx\n"
                        "\tmmio_len:%d\n"
                        "\taccel:%d\n"
           "\n",
           finfo.id, finfo.smem_start, finfo.smem_len, finfo.type,
           finfo.type_aux, finfo.visual, finfo.xpanstep, finfo.ypanstep,
           finfo.ywrapstep, finfo.line_length, finfo.mmio_start,
           finfo.mmio_len, finfo.accel);
}

//打印fb驱动中var结构信息,注:fb驱动加载后,var结构可根据实际需要被重置
void
printVariableInfo ()
{
   printf ("Variable screen info:\n"
                        "\txres:%d\n"
                        "\tyres:%d\n"
                        "\txres_virtual:%d\n"
                        "\tyres_virtual:%d\n"
                        "\tyoffset:%d\n"
                        "\txoffset:%d\n"
                        "\tbits_per_pixel:%d\n"
                        "\tgrayscale:%d\n"
                        "\tred: offset:%2d, length: %2d, msb_right: %2d\n"
                        "\tgreen: offset:%2d, length: %2d, msb_right: %2d\n"
                        "\tblue: offset:%2d, length: %2d, msb_right: %2d\n"
                        "\ttransp: offset:%2d, length: %2d, msb_right: %2d\n"
                        "\tnonstd:%d\n"
                        "\tactivate:%d\n"
                        "\theight:%d\n"
                        "\twidth:%d\n"
                        "\taccel_flags:0x%x\n"
                        "\tpixclock:%d\n"
                        "\tleft_margin:%d\n"
                        "\tright_margin: %d\n"
                        "\tupper_margin:%d\n"
                        "\tlower_margin:%d\n"
                        "\thsync_len:%d\n"
                        "\tvsync_len:%d\n"
                        "\tsync:%d\n"
                       "\tvmode:%d\n"
           "\n",
           vinfo.xres, vinfo.yres, vinfo.xres_virtual, vinfo.yres_virtual,
           vinfo.xoffset, vinfo.yoffset, vinfo.bits_per_pixel,
           vinfo.grayscale, vinfo.red.offset, vinfo.red.length,
            vinfo.red.msb_right,vinfo.green.offset, vinfo.green.length,
           vinfo.green.msb_right, vinfo.blue.offset, vinfo.blue.length,
           vinfo.blue.msb_right, vinfo.transp.offset, vinfo.transp.length,
           vinfo.transp.msb_right, vinfo.nonstd, vinfo.activate,
           vinfo.height, vinfo.width, vinfo.accel_flags, vinfo.pixclock,
           vinfo.left_margin, vinfo.right_margin, vinfo.upper_margin,
           vinfo.lower_margin, vinfo.hsync_len, vinfo.vsync_len,
           vinfo.sync, vinfo.vmode);
}

//画大小为width*height的同色矩阵,8alpha+8reds+8greens+8blues
void
drawRect_rgb32 (int x0, int y0, int width,int height, int color)
{
   const int bytesPerPixel = 4;
   const int stride = finfo.line_length / bytesPerPixel;

   int *dest = (int *) (frameBuffer)
       + (y0 + vinfo.yoffset) * stride + (x0 + vinfo.xoffset);

   int x, y;
   for (y = 0; y < height; ++y)
    {
       for (x = 0; x < width; ++x)
       {
           dest[x] = color;
        }
       dest += stride;
    }
}

//画大小为width*height的同色矩阵,5reds+6greens+5blues
void
drawRect_rgb16 (int x0, int y0, int width,int height, int color)
{
   const int bytesPerPixel = 2;
   const int stride = finfo.line_length / bytesPerPixel;
   const int red = (color & 0xff0000) >> (16 + 3);
   const int green = (color & 0xff00) >> (8 + 2);
   const int blue = (color & 0xff) >> 3;
   const short color16 = blue | (green << 5) | (red << (5 +6));

   short *dest = (short *) (frameBuffer)
        + (y0 + vinfo.yoffset) * stride + (x0 +vinfo.xoffset);

   int x, y;
   for (y = 0; y < height; ++y)
    {
       for (x = 0; x < width; ++x)
       {
           dest[x] = color16;
       }
       dest += stride;
    }
}

//画大小为width*height的同色矩阵,5reds+5greens+5blues
void
drawRect_rgb15 (int x0, int y0, int width,int height, int color)
{
   const int bytesPerPixel = 2;
   const int stride = finfo.line_length / bytesPerPixel;
   const int red = (color & 0xff0000) >> (16 + 3);
   const int green = (color & 0xff00) >> (8 + 3);
   const int blue = (color & 0xff) >> 3;
   const short color15 = blue | (green << 5) | (red << (5 + 5))| 0x8000;

   short *dest = (short *) (frameBuffer)
       + (y0 + vinfo.yoffset) * stride + (x0 + vinfo.xoffset);

   int x, y;
   for (y = 0; y < height; ++y)
    {
       for (x = 0; x < width; ++x)
       {
           dest[x] = color15;
       }
       dest += stride;
    }
}

void
drawRect (int x0, int y0, int width, intheight, int color)
{
   switch (vinfo.bits_per_pixel)
    {
   case 32:
       drawRect_rgb32 (x0, y0, width, height, color);
       break;
   case 16:
       drawRect_rgb16 (x0, y0, width, height, color);
       break;
   case 15:
       drawRect_rgb15 (x0, y0, width, height, color);
       break;
   default:
       printf ("Warning: drawRect() not implemented for color depth%i\n",
                vinfo.bits_per_pixel);
       break;
    }
}

#define PERFORMANCE_RUN_COUNT 5
void
performSpeedTest (void *fb, int fbSize)
{
   int i, j, run;
   struct timeval startTime, endTime;
   unsigned long long results[PERFORMANCE_RUN_COUNT];
   unsigned long long average;
   unsigned int *testImage;

   unsigned int randData[17] = {
        0x3A428472, 0x724B84D3, 0x26B898AB,0x7D980E3C, 0x5345A084,
       0x6779B66B, 0x791EE4B4, 0x6E8EE3CC, 0x63AF504A, 0x18A21B33,
       0x0E26EB73, 0x022F708E, 0x1740F3B0, 0x7E2C699D, 0x0E8A570B,
       0x5F2C22FB, 0x6A742130
   };

   printf ("Frame Buffer Performance test...\n");
   for (run = 0; run < PERFORMANCE_RUN_COUNT; ++run)
    {
       /* Generate test image with random(ish) data: */
       testImage = (unsigned int *) malloc (fbSize);
       j = run;
       for (i = 0; i < (int) (fbSize / sizeof (int)); ++i)
       {
           testImage[i] = randData[j];
           j++;
           if (j >= 17)
                j = 0;
       }

       gettimeofday (&startTime, NULL);
       memcpy (fb, testImage, fbSize);
       gettimeofday (&endTime,NULL);

       long secsDiff = endTime.tv_sec - startTime.tv_sec;
                results[run] =
                    secsDiff * 1000000 +(endTime.tv_usec - startTime.tv_usec);

                free (testImage);
    }

   average = 0;
   for (i = 0; i < PERFORMANCE_RUN_COUNT; ++i)
       average += results[i];
   average = average / PERFORMANCE_RUN_COUNT;

   printf (" Average: %llu usecs\n", average);
   printf (" Bandwidth: %.03f MByte/Sec\n",
           (fbSize / 1048576.0) / ((double) average / 1000000.0));
   printf (" Max. FPS: %.03f fps\n\n",
           1000000.0 / (double) average);

   /* Clear the framebuffer back to black again: */
   memset (fb, 0, fbSize);
}

int
main (int argc, char **argv)
{
   const char *devfile = "/dev/fb0";
   long int screensize = 0;
   int fbFd = 0;

   /* Open the file for reading and writing */
   fbFd = open (devfile, O_RDWR);
   if (fbFd == -1)
    {
       perror ("Error: cannot open framebuffer device");
       exit (1);
    }

   //获取finfo信息并显示
   if (ioctl (fbFd, FBIOGET_FSCREENINFO, &finfo) == -1)
    {
       perror ("Error reading fixed information");
       exit (2);
    }
   printFixedInfo ();
   //获取vinfo信息并显示
   if (ioctl (fbFd, FBIOGET_VSCREENINFO, &vinfo) == -1)
    {
       perror ("Error reading variable information");
       exit (3);
    }
   printVariableInfo ();

   /* Figure out the size of the screen in bytes */
   screensize = finfo.smem_len;

   /* Map the device to memory */
       frameBuffer =
           (char *) mmap (0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED,
                           fbFd, 0);
       if (frameBuffer == MAP_FAILED)
       {
           perror ("Error: Failed to map framebuffer device to memory");
           exit (4);
       }

       //测试virt fb的性能
       performSpeedTest (frameBuffer, screensize);

       printf ("Will draw 3 rectangles on the screen,\n"
                "they should be coloredred, green and blue (in that order).\n");
       drawRect (vinfo.xres / 8, vinfo.yres / 8,
                  vinfo.xres / 4, vinfo.yres /4, 0xffff0000);
       drawRect (vinfo.xres * 3 / 8, vinfo.yres * 3 / 8,
                  vinfo.xres / 4, vinfo.yres / 4,0xff00ff00);
       drawRect (vinfo.xres * 5 / 8, vinfo.yres * 5 / 8,
                  vinfo.xres / 4, vinfo.yres /4, 0xff0000ff);

       sleep (5);
       printf (" Done.\n");

       munmap (frameBuffer, screensize);   //解除内存映射,与mmap对应

       close (fbFd);
       return 0;
}

该程序需要在打开FrameBuffer的终端模式下运行,我使用的Ubuntu 12.04,直接按Ctrl + Alt + F1,切换到终端1下,即可运行该程序。程序运行效果如下图所示:

说明一下,在终端模式下,截图软件我用的是fbgrab。

在我的电脑上,该程序在终端打印的信息如下:

Fixed screen info:
       id: inteldrmfb
       smem_start: 0xd0064000
       smem_len: 8294400
       type: 0
       type_aux: 0
       visual: 2
       xpanstep: 1
       ypanstep: 1
       ywrapstep: 0
       line_length: 7680
       mmio_start: 0x0
       mmio_len: 0
       accel: 0

Variable screen info:
       xres: 1920
       yres: 1080
       xres_virtual: 1920
       yres_virtual: 1080
       yoffset: 0
       xoffset: 0
       bits_per_pixel: 32
       grayscale: 0
       red: offset: 16, length:  8,msb_right:  0
       green: offset:  8, length:  8, msb_right: 0
       blue: offset:  0, length:  8, msb_right: 0
       transp: offset:  0, length:  0, msb_right: 0
       nonstd: 0
       activate: 0
       height: -1
       width: -1
       accel_flags: 0x1
       pixclock: 0
       left_margin: 0
       right_margin: 0
       upper_margin: 0
       lower_margin: 0
       hsync_len: 0
       vsync_len: 0
       sync: 0
       vmode: 0

Frame Buffer Performance test...
 Average: 1489 usecs
 Bandwidth: 5312.395 MByte/Sec
 Max.FPS: 671.592 fps

Will draw 3 rectangles on the screen,
they should be colored red, green and blue(in that order).
 Done.

通过这个测试程序,我们就能理解怎样在Linux用户空间,基于FrameBuffer接口,绘制想要的图形。

时间: 2024-10-10 20:43:54

Linux FrameBuffer分析之编写基于FrameBuffer接口的应用程序的相关文章

Hadoop基础学习(一)分析、编写并运行WordCount词频统计程序

前面已经在我的Ubuntu单机上面搭建好了伪分布模式的HBase环境,其中包括了Hadoop的运行环境. 详见我的这篇博文:http://blog.csdn.net/jiyiqinlovexx/article/details/29208703 我的目的主要是学习HBase,下一步打算学习的是将HBase作为Hadoop作业的输入和输出. 但是好像以前在南大上学时学习的Hadoop都忘记得差不多了,所以找到以前上课做的几个实验:wordCount,PageRank以及InversedIndex.

嵌入式Linux基于framebuffer的jpeg格式本地LCD屏显示

在基于Linux的视频监控采集系统中,摄像头采集到的一帧视频图像数据一般都是经过硬件自动压缩成jpeg格式的,然后再保存到摄像头设备的缓冲区.如果要把采集到的jpeg格式显示在本地LCD屏上,由于我们的Linux系统没有移植任何GUI系统,就要考虑以下方面:1. 将jpeg格式解压缩为位图格式,也就是jpeg解码. 2. 将解码出来的位图格式输出到本地的LCD屏上. 在Linux系统下是通过写入帧缓冲(framebuffer)来实现的. 3. framebuffer相当于为LCD设备提供一个统一

【SylixOS】Qt 基于FrameBuffer渲染界面

简介 1 SylixOSFB 12.1 插件的初始化 12.2 窗口绘制 12.3 SylixOSFB的实现 2 1.简介Qt是目前一款比较主流的人机交互界面库.它有很强的跨平台能力,可移植性好,被广泛应用在PC端以及嵌入式领域.Qt可大致分为两部分:QtGui和QtCore,QtGui提供开发人员一套完整的开发控件,可以快速开发客户端界面:QtCore则负责底层渲染以及事件驱动等.而本章节主要介绍的是Qt的渲染机制,在Qt5中将底层渲染和窗口管理大致分为:SylixOSFB.LinuxFB.K

Linux内核分析实验五

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 刘旸 + 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 在操作系统上运行的某个应用程序,如果

超全整理!Linux性能分析工具汇总合集

出于对Linux操作系统的兴趣,以及对底层知识的强烈欲望,因此整理了这篇文章.本文也可以作为检验基础知识的指标,另外文章涵盖了一个系统的方方面面.如果没有完善的计算机系统知识,网络知识和操作系统知识,文档中的工具,是不可能完全掌握的,另外对系统性能分析和优化是一个长期的系列. 本文档主要是结合Linux 大牛,Netflix 高级性能架构师 Brendan Gregg 更新 Linux 性能调优工具的博文,搜集Linux系统性能优化相关文章整理后的一篇综合性文章,主要是结合博文对涉及到的原理和性

Linux内核分析方法谈

本文来自 http://blog.csdn.net/ouyang_linux007/article/details/7422346 Linux的最大的好处之一就是它的源码公开.同时,公开的核心源码也吸引着无数的电脑爱好者和程序员:他们把解读和分析Linux的核心源码作为自己的最大兴趣,把修改Linux源码和改造Linux系统作为自己对计算机技术追求的最大目标. Linux内核源码是很具吸引力的,特别是当你弄懂了一个分析了好久都没搞懂的问题:或者是被你修改过了的内核,顺利通过编译,一切运行正常的时

linux内核分析(网课期末&amp;地面课期中)

堆栈变化过程: Linux内核分析——计算机是如何工作的 计算机是如何工作的?(总结)——三个法宝 存储程序计算机工作模型,计算机系统最最基础性的逻辑结构: 函数调用堆栈,高级语言得以运行的基础,只有机器语言和汇编语言的时候堆栈机制对于计算机来说并不那么重要,但有了高级语言及函数,堆栈成为了计算机的基础功能: enter pushl %ebp movl %esp,%ebp leave movl %ebp,%esp popl %ebp 函数参数传递机制和局部变量存储 中断,多道程序操作系统的基点,

《Linux内核分析》课程第一周学习总结

姓名:何伟钦 学号:20135223 ( *原创作品转载请注明出处*) ( 学习课程:<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 学习内容:通过汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的 第一部分:视频教学笔记总结 一.存储程序计算机 冯诺依曼体系结构概念:即具有存储程序计算机的体系结构,大多数拥有计算和存储功能的设备(手机.平板.计算机等)其核心构造均为冯诺依曼体系结构 冯诺依曼体系结构工作

Linux内核分析(五)----字符设备驱动实现

原文:Linux内核分析(五)----字符设备驱动实现 Linux内核分析(五) 昨天我们对linux内核的子系统进行简单的认识,今天我们正式进入驱动的开发,我们今后的学习为了避免大家没有硬件的缺陷,我们都会以虚拟的设备为例进行学习,所以大家不必害怕没有硬件的问题. 今天我们会分析到以下内容: 1.      字符设备驱动基础 2.      简单字符设备驱动实现 3.      驱动测试 l  字符设备基础 1.       字符设备描述结构 在linux2.6内核中,使用cdev结构体描述一