`
no791no
  • 浏览: 18877 次
社区版块
存档分类
最新评论

Linux下FrameBuffer直接写屏

 
阅读更多

Linux下FrameBuffer直接写屏
2011年09月20日
  "Linux下FrameBuffer直接写屏"
  因为Linux是工作在保护模式下,所以用户态进程是无法象DOS那样使用显卡BIOS里
  提供的中断调用来实现直接写屏,故Linux抽象出FrameBuffer这个设备来供用户态
  进程实现直接写屏。
  在继续下面的之前,先说明几个背景知识:
  1、FrameBuffer主要是根据VESA标准的实现的,所以只能实现最简单的功能。
  2、由于涉及内核的问题,FrameBuffer是不允许在系统起来后修改显示模式等一系
  列操作。(好象很多人都想要这样干,这是不被允许的,当然如果你自己与驱动
  的话,是可以实现的)
  3、对FrameBuffer的操作,会直接影响到本机的所有控制台的输出,包括XWIN的图
  形界面。
  好,现在可以让我们开始实现直接写屏:
  1、打开一个FrameBuffer设备
  2、通过mmap调用把显卡的物理内存空间映射到用户空间
  3、直接写内存。
  好象很简单哦~
  fbtools.h
  #ifndef _FBTOOLS_H_
  #define _FBTOOLS_H_
  #include
  //a framebuffer device structure;
  typedef struct fbdev{
  int fb;
  unsigned long fb_mem_offset;
  unsigned long fb_mem;
  struct fb_fix_screeninfo fb_fix;
  struct fb_var_screeninfo fb_var;
  char dev[20];
  } FBDEV, *PFBDEV;
  //open & init a frame buffer
  //to use this function,
  //you must set FBDEV.dev=\"/dev/fb0\"
  //or \"/dev/fbX\"
  //it\'s your frame buffer.
  int fb_open(PFBDEV pFbdev);
  //close a frame buffer
  int fb_close(PFBDEV pFbdev);
  //get display depth
  int get_display_depth(PFBDEV pFbdev);
  //full screen clear
  void fb_memset(void *addr, int c, size_t len);
  #endif
  fbtools.c
  #include
  #include
  #include
  #include
  #include
  #include
  #include
  #include
  #include \"fbtools.h\"
  #define TRUE 1
  #define FALSE 0
  #define MAX(x,y) ((x)>(y)?(x):(y))
  #define MIN(x,y) ((x)fb = open(pFbdev->dev, O_RDWR);
  if(pFbdev->fb dev);
  return FALSE;
  }
  if (-1 == ioctl(pFbdev->fb,FBIOGET_VSCREENINFO,&(pFbdev->fb_var)))
  {
  printf(\"ioctl FBIOGET_VSCREENINFO\\n\");
  return FALSE;
  }
  if (-1 == ioctl(pFbdev->fb,FBIOGET_FSCREENINFO,&(pFbdev->fb_fix)))
  {
  printf(\"ioctl FBIOGET_FSCREENINFO\\n\");
  return FALSE;
  }
  //map physics address to virtual address
  pFbdev->fb_mem_offset = (unsigned long)(pFbdev->fb_fix.smem_start) & (~PAGE_MASK);
  pFbdev->fb_mem = (unsigned long int)mmap(NULL, pFbdev->fb_fix.smem_len +
  pFbdev->fb_mem_offset,
  PROT_READ | PROT_WRITE, MAP_SHARED, pFbdev->fb, 0);
  if (-1L == (long) pFbdev->fb_mem)
  {
  printf(\"mmap error! mem:%d offset:%d\\n\", pFbdev->fb_mem,
  pFbdev->fb_mem_offset);
  return FALSE;
  }
  return TRUE;
  }
  //close frame buffer
  int fb_close(PFBDEV pFbdev)
  {
  close(pFbdev->fb);
  pFbdev->fb=-1;
  }
  //get display depth
  int get_display_depth(PFBDEV pFbdev);
  {
  if(pFbdev->fbfb_var.bits_per_pixel;
  }
  //full screen clear
  void fb_memset (void *addr, int c, size_t len)
  {
  memset(addr, c, len);
  }
  //use by test
  #define DEBUG
  #ifdef DEBUG
  main()
  {
  FBDEV fbdev;
  memset(&fbdev, 0, sizeof(FBDEV));
  strcpy(fbdev.dev, \"/dev/fb0\");
  if(fb_open(&fbdev)==FALSE)
  {
  printf(\"open frame buffer error\\n\");
  return;
  }
  fb_memset(fbdev.fb_mem + fbdev.fb_mem_offset, 0, fbdev.fb_fix.smem_len);
  fb_close(&fbdev);
  }
  发帖时间 : 2006-07-16 23:36:41                    
  "FrameBuffer"
  FrameBuffer 是出现在 2.2.xx 内核当中的一种驱动程序接口。这种接口将显示设备抽象为帧缓冲区。用户可以将它看成是显示内存的一个映像,将其映射到进程地址空间之后,就可以直接进行读写操作,而写操作可以立即反应在屏幕上。该驱动程序的设备文件一般是 /dev/fb0、/dev/fb1 等等。比如,假设现在的显示模式是 1024x768-8 位色,则可以通过如下的命令清空屏幕:
  $ dd if=/dev/zero of=/dev/fb0 bs=1024 count=768
  在应用程序中,一般通过将 FrameBuffer 设备映射到进程地址空间的方式使用,比如下面的程序就打开 /dev/fb0 设备,并通过 mmap 系统调用进行地址映射,随后用 memset 将屏幕清空(这里假设显示模式是 1024x768-8 位色模式,线性内存模式):
  int fb;
  unsigned char* fb_mem;
  fb = open (“/dev/fb0”, O_RDWR);
  fb_mem = mmap (NULL, 1024*768, PROT_READ|PROT_WRITE,MAP_SHARED,fb,0);
  memset (fb_mem, 0, 1024*768);
  FrameBuffer 设备还提供了若干 ioctl 命令,通过这些命令,可以获得显示设备的一些固定信息(比如显示内存大小)、与显示模式相关的可变信息(比如分辨率、象素结构、每扫描线的字节宽度),以及伪彩色模式下的调色板信息等等。
  通过 FrameBuffer 设备,还可以获得当前内核所支持的加速显示卡的类型(通过固定信息得到),这种类型通常是和特定显示芯片相关的。比如目前最新的内核(2.4.9)中,就包含有对 S3、Matrox、nVidia、3Dfx 等等流行显示芯片的加速支持。在获得了加速芯片类型之后,应用程序就可以将 PCI 设备的内存I/O(memio)映射到进程的地址空间。这些 memio 一般是用来控制显示卡的寄存器,通过对这些寄存器的操作,应用程序就可以控制特定显卡的加速功能。
  PCI 设备可以将自己的控制寄存器映射到物理内存空间,而后,对这些控制寄存器的访问,给变成了对物理内存的访问。因此,这些寄存器又被称为“memio”。一旦被映射到物理内存,Linux 的普通进程就可以通过 mmap 将这些内存 I/O 映射到进程地址空间,这样就可以直接访问这些寄存器了。
  当然,因为不同的显示芯片具有不同的加速能力,对memio 的使用和定义也各自不同,这时,就需要针对加速芯片的不同类型来编写实现不同的加速功能。比如大多数芯片都提供了对矩形填充的硬件加速支持,但不同的芯片实现方式不同,这时,就需要针对不同的芯片类型编写不同的用来完成填充矩形的函数。
  说到这里,读者可能已经意识到 FrameBuffer 只是一个提供显示内存和显示芯片寄存器从物理内存映射到进程地址空间中的设备。所以,对于应用程序而言,如果希望在 FrameBuffer 之上进行图形编程,还需要完成其他许多工作。举个例子来讲,FrameBuffer 就像一张画布,使用什么样子的画笔,如何画画,还需要你自己动手完成。
  发帖时间 : 2006-07-16 23:45:44                    
  "Re:Linux下FrameBuffer直接写屏"
  对FrameBuffer的研究
  大家都知道Unix/Linux系统是由命令驱动的。那么最基本的系统是命令行的(就是想DOS一样的界面)。X-Window- System是Unix/Linux上的图形系统,它是通过X-Server来控制硬件的。但有一些Linux的发行版在引导的时候就会在屏幕上出现图形,这时的图形是不可能由X来完成的,那是什么机制呢?答案是FrameBuffer。
  FrameBuffer不是一个图形系统,更不是窗口系统。它比X要低级,简单来说FrameBuffer就是一种机制的实现。这种机制是把屏幕上的每个点映射成一段线性内存空间,程序可以简单的改变这段内存的值来改变屏幕上某一点的颜色。X的高度可移植性就是来自于这种机制,不管是在那种图形环境下,只要有这种机制的实现就可以运行X。所以在几乎所有的平台上都有相应的X版本的移植。
  好了,闲话少说,下面我们来看看可以利用FrameBuffer来干点什么。首先看看你是否有了相应的驱动:找一下在/dev/下是否有fb*这个设备文件,这是个字符类的特殊文件。
  ls -l /dev/fb0 (Enter)
  crw-rw---- 1 root video 29, 0 Jan 27 15:32 /dev/fb0
  如果没有这个文件也可以找找其他的比如:/dev/fb1,/dev/fb2...如果找不到这些文件,那就得重新编译内核了。下面假设存在这个文件/dev/fb0,这就是FrameBuffer的设备文件。
  有了这个我们可以play with FrameBuffer了。(一下的操作不一定要在X下,可以在启动了FrameBuffer的虚拟控制台下)
  cat /dev/fb0 > sreensnap
  ls -l sreensnap
  -rw-r--r-- 1 wsw wsw 6291456 Jan 27 21:30 sreensnap
  我们得到了一个恰好6M的文件,再做下面的操作:
  clear /*清楚屏幕的输出*/
  cat sreensnap > /dev/fb0
  是不是奇怪的事情发生了?好像是中了病毒一般?屏幕又恢复了以前的状态?不用着急,
  clear
  这样屏幕就正常了。
  通过以上的操作,我想你也猜到了。文件/dev/fb0就是控制屏幕上的每一点的颜色的文件。我们可以写程序来改变这个文件的内容,就可以方便的在屏幕上画图了:-)
  我下面就来写一个小程序,探测一下屏幕的属性。
  #include
  #include
  #include
  #include
  #include
  int main () {
  int fp=0;
  struct fb_var_screeninfo vinfo;
  struct fb_fix_screeninfo finfo;
  fp = open ("/dev/fb0",O_RDWR);
  if (fp 内存大小。
  __u32 line_length 是屏幕上一行的点在内存中占有的空间,不是一行上的点数。
  在fb_var_screeninfo 中有
  __u32 xres ,__u32 yres 是x和y方向的分辨率,就是两个方向上的点数。
  __u32 bits_per_pixel 是每一点占有的内存空间。
  把上面的程序编译以后运行,在我的机器上的结果如下:
  The mem is :6291456
  The line_length is :4096
  The xres is :1024
  The yres is :768
  bits_per_pixel is :32
  内存长度恰好是6M,每行占有4M的空间,分辨率是1024x768,色彩深度是32位。细心的你可能已经发现有些不对。屏幕上的点有1024x768= 786432个,每个点占有32比特。屏幕一共的占有内存数为32x786432=25165824 就是3145728字节,恰好是3M但是上面的程序告诉我们有6M的存储空间。这是因为在现代的图形系统中大多有缓冲技术,显存中存有两页屏幕数据,这是方便快速的改变屏幕内容实现动画之类比较高的要求。关于这种缓冲技术有点复杂,我们目前先不讨论。对于我们来说只有这3M内存来存放这一个屏幕的颜色数据。
  好了,现在你应该对FrameBuffer有一个大概的了解了吧。那么接下来你一定会想在屏幕上画一些东西,让我们先从画一个点开始吧。先说说我的想法:在类Unix系统中,一切东西都是文件。我们对屏幕的读写就可以转换成对/dev/fb0的读写。那么就把/dev/fb0用open打开,再用 lseek定位要读写的位置,最后调用read或者write来操作。通过这么一大段的操作我们才完成了对一个点的读或者写。这种方法开销太大了。还有一种方法,我们把/dev/fb0映射到程序进程的内存空间中来,然后得到一个指向这段存储空间的指针,这样就可以方便的读写了。但是我们要知道能映射多少和该映射多少,这能很方便的从上面一个程序得出的参数来决定。
  下面是程序代码:
  #include
  #include
  #include
  #include
  #include
  int main () {
  int fp=0;
  struct fb_var_screeninfo vinfo;
  struct fb_fix_screeninfo finfo;
  long screensize=0;
  char *fbp = 0;
  int x = 0, y = 0;
  long location = 0;
  fp = open ("/dev/fb0",O_RDWR);
  if (fp 出来,得到一个指向这块空间的指针*/
  fbp =(char *) mmap (0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fp,0);
  if ((int) fbp == -1)
  {
  printf ("Error: failed to map framebuffer device to memory.\n");
  exit (4);
  }
  /*这是你想画的点的位置坐标,(0,0)点在屏幕左上角*/
  x = 100;
  y = 100;
  location = x * (vinfo.bits_per_pixel / + y * finfo.line_length;
  *(fbp + location) = 100; /* 蓝色的色深 */ /*直接赋值来改变屏幕上某点的颜色*/
  *(fbp + location + 1) = 15; /* 绿色的色深*/
  *(fbp + location + 2) = 200; /* 红色的色深*/
  *(fbp + location + 3) = 0; /* 是否透明*/
  munmap (fbp, screensize); /*解除映射*/
  close (fp); /*关闭文件*/
  return 0;
  }
  因为这是对线性存储空间的读写,所以代码有点不清晰,不易理解。但是有了这个基本的代码实现,我们可以很容易写一些DrawPoint之类的函数去包装一下低层的对线性存储空间的读写。但是有了画点的程序,再写出画线画圆的函数就不是非常困难了。
  这些就是我对FrameBuffer的初步研究,匆忙之间写些东西不成文章,以后要写些更高级一点的函数的实现。
  发帖时间 : 2006-07-23 21:46:15                    
  "Linux Framebuffer Driver Writing Howto"
  本文档描述了如何为Linux支持一个framebuffer(帧缓冲)视频卡。列出了所支持的视频硬件,描述如何进行内核驱动编程,回答了一些经常遇到的问题。
  目的是带动当前的也是新的framebuffer驱动写作者尽快成为一个在Linux的图形系统中的新开发者
  1.简介
  这是一份Linux FrameBuffer驱动的Howto,意在覆盖 在Linux编写一个framebuffer视频驱动你需要知道的东西的 快速参考,也回答了在Linux设置视频模式的
  一些常见问题。并给出了 与计算机图形相关的一些主题的参考资料。如果你不是很熟悉视频硬件的话,可能需要多次查看本文档。
  本文所涉猎 仅局限在 为Linux写一个可设置模式的视频卡framebuffer驱动。参考资料中列出了如何设置framebuffer卡,和安装XFB_Dev X Server
  3.计算视频模式
  如果你看到fbdev驱动,你会很惊讶。是的,它很复杂,但也许不是你想象的那么复杂。关于标准模式的边注--视频卡不能做任何事情,除了VGA/VESA制定的
  标准模式,比如640x480, 800x600, 1024x768, 1280x960。这是一个误解。大多数显示卡,任何分辨率都能使用(programmed).并且硬件加速器还没有为上面的
  提到的这些模式进行优化。所以,使用其他的宽度是不明智的,因为这需要关闭硬件加速支持。所以,如果你写一个驱动,不要固执地使用这些模式。如果卡能处理他,允许任何模式。
  另外,显示器也对 我们可以使用何种模式 有重要影响。有两种基本类型的显示器:固定频率(它们通常可以使用多个场频,但这没什么用,因为它们通常都很低)和 多个频率
  3.1 固定平率的显示器
   这种显示器的手册中说,行频(horizontal frequency)是31.5KHz
    我们想显示一个指定的模式,比如640x480
  我们现在已经可以决定我们所需要的绝对最小点频率
       dotclock = horiz_total * hfreq
  和
       horiz_total = width + right_boader + sync + left_border> width
    最小的dotclock算出来是20.16MHz. 我们将可能需要 为边界(border)和同步(sync)留出 约20% 的裕度("slack")
  所以说,我们需要大约24MHz的时钟。现在我们看看我们的卡能处理的下个更高的频率大概是 25.175MHz,如果我们的这张卡是
  VGA兼容卡
    现在我们可以计算horizontal total
  horiz_total = dotclock/hfreq = 799.2
  我们只能以8的倍数编程,所以取800. 现在,我们还需要决定 sync pluse的长度和placement, sync pluse给出所有剩余的参数
  对这些没有很清洁的数学要求.技术上,sync必须足够长,能被detected.并且必须居中.居中并不是要求那么迫切.现在数控显示器(digitally controlled monitors)很普遍了,允许从外部控制居中这些问题.一般,你应该早一些放置sync pluse,也就是说,让right_border 小一些
分享到:
评论

相关推荐

    通过framebuffer直接写屏

    通过framebuffer直接写屏 自动判断走是走fb还是qvfb; 目标平台为16位深度值,由于16位色rgb565图片(使用linux下GIMP工具将png转换为bmp,再使用dd命名去掉文件头将bmp转换为原始图片文件;也可使用ffmpeg命令转)...

    Linux操作系统下使用FrameBuffer直接写屏

    Linux是工作在保护模式下,所以用户态进程是无法象DOS那样使用显卡BIOS里提供的中断调用来实现直接写屏,故Linux抽象出FrameBuffer这个设备来供用户态进程实现直接写...本文简单介绍了使用FrameBuffer直接写屏的方法。

    如何在Linux操作系统下用FrameBuffer直接写屏

    因为Linux是工作在保护模式下,所以用户态进程是无法象DOS那样使用显卡BIOS里提供的中断调用来实现直接写屏,故Linux抽象出FrameBuffer这个设备来供用户态进程实现直接写屏。本文介绍了对FrameBuffer的操作方法。

    Linux设备驱动之Framebuffer分析

    Framebuffer将显示设备抽象为帖缓冲区,用户通过内存映射到进程地址空间之后,就可以直接进行读写操作,且写操作可以立即在屏幕上进行显示,在Linux内核/linux/drivers/video/下有相关的显示驱动与接口,其中...

    STM32MP157实现FrameBuffer驱动LCD屏幕【支持STM32MP1系列单片机_Linux C驱动】.zip

    STM32MP157 Linux C驱动程序,支持STM32MP1系列单片机。 项目代码可直接编译运行。

    基于Linux的人机交互接口设备驱动程序的设计

    而LCD设备采用Unity805plus内置的LCD控制器与系统进行通讯,利用帧缓冲(framebuffer)设备作为接口,使上层应用程序能够在图形模式下直接对显示缓冲区进行统一的读写操作。文中按照驱动的设计流程为主线给出了各...

    技术文章:嵌入式Linux中如何进行截屏?

    原理 由于 Linux 系统的 FrameBuffer 机制,会把屏幕上的每个点映射成一段线性内存空间,程序就可以通过改变这段内存的值来改变屏幕上某一点的颜色。屏幕色彩的原始数据保存在/dev/fb0文件内,因此我们可以直接cat...

    用户图形接口GUI.ppt

    关于触摸屏的校准 :由于触摸屏接口实现类是从特殊的类QCalibratedMouseHandler继承的,已经实现了坐标的校准,一般直接读取坐标的位置和状态即可。 Qt/Embedded具有采用FrameBuffer作为底层图形接口、能够运行在被...

    微型嵌入式GUI演示程序

    可以支持 Borland 公司的 BGI(或兼容) 接口 图形驱动,也可使用自行编写的直接写屏驱动; Linux 下可以使用 FrameBuffer 作为底层显示驱动. (注:在PC RedHat Linux 9 测试运行成功) GUI可提供一个桌面环境,拥有任务栏...

    基于GEC210的语音识别控制

    1、通过文件检索可以将固定的目录下的三种类型的图片和音乐给检索出来,然后再利用libjpeg库和libpng库来对jpeg图片和png图片进行解码,再通过直接操作framebuffer来将图片显示在LCD屏上,还可以使用触摸屏来切换...

    example4.rar_驱动编程_Unix_Linux_

    framebuffer文件实例framebuffer是出现在内核中的驱动程序的接口。...可以把它看成是显示内存的一个映像,将其映射到进程地址空间以后,就可以直接进行读写操作,并且写操作可以直接反应在屏幕上。

    Kindle上的开源阅读器Koreader.zip

    KOReader 自带一套超轻量级的GUI框架,可直接运行在支持桢缓存(FrameBuffer)设备的阅读器上,也可以通过 SDL 获得跨平台的运行支持。 Koreader 自带一个设备模拟器,方便开发者在桌面系统进行开发。有关开发的...

    精通Qt4编程(第二版)源代码

    嵌入式Linux,包括支持framebuffer的所有Linux平台。 \Qt还支持嵌入式系统,Qt的嵌入式版本称为Qtopia Core,可以在多种处理器上运行,目标操作系统通常是嵌入式Linux。Qtopia Core应用程序直接使用framebuffer,...

    精通qt4编程(源代码)

    嵌入式Linux,包括支持framebuffer的所有Linux平台。 \Qt还支持嵌入式系统,Qt的嵌入式版本称为Qtopia Core,可以在多种处理器上运行,目标操作系统通常是嵌入式Linux。Qtopia Core应用程序直接使用framebuffer,而...

Global site tag (gtag.js) - Google Analytics