首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

Linux下FrameBuffer直接写屏

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 <linux/fb.h>


      //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 <stdio.h>
      #include <stdlib.h>
      #include <fcntl.h>
      #include <unistd.h>
      #include <string.h>
      #include <sys/ioctl.h>
      #include <sys/mman.h>
      #include <asm/page.h>


      #include \"fbtools.h\"


      #define TRUE 1
      #define FALSE 0
      #define MAX(x,y) ((x)>(y)?(x)y))
      #define MIN(x,y) ((x)<(y)?(x)y))


      //open & init a frame buffer
      int fb_open(PFBDEV pFbdev)
      {
      pFbdev->fb = open(pFbdev->dev, O_RDWR);
      if(pFbdev->fb < 0)
      {
      printf(\"Error opening %s: %m. Check kernel config\\", pFbdev->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->fb<=0)
      {
      printf(\"fb device not open, open it first\\n\");
      return FALSE;
      }
      return pFbdev->fb_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);
      }

返回列表