511929155 阅读(120) 评论(0)
pre.cjk { font-family: "Courier New",monospace; }h2.cjk { font-family: "Noto Sans CJK SC Regular"; }h2.ctl { font-family: "FreeSans"; }h1 { margin-bottom: 0.08in; }h1.western { font-family: "Liberation Serif",serif; }h1.cjk { font-family: "Noto Sans CJK SC Regular"; font-size: 24pt; }h1.ctl { font-family: "FreeSans"; font-size: 24pt; }p { margin-bottom: 0.1in; line-height: 120%; }a:link { }

Linux framebuffer 帧缓冲的使用

framebuffer 帧缓冲

帧缓冲(framebuffer)是Linux 系统为显示设备提供的一个接口,它将显示缓冲区抽象,屏蔽图像硬件的底层差异,允许上层应用程序在图形模式下直接对显示缓冲区进行读写操作。用户不必关心物理显示缓冲区的具体位置及存放方式,这些都由帧缓冲设备驱动本身来完成。
    framebuffer机制模仿显卡的功能,将显卡硬件结构抽象为一系列的数据结构,可以通过framebuffer的读写直接对显存进行操作。用户可以将framebuffer看成是显存的一个映像,将其映射到进程空间后,就可以直接进行读写操作,写操作会直接反映在屏幕上。

帧缓冲设备为标准的字符型设备,在Linux中主设备号29,定义在/include/linux/major.h中的FB_MAJOR,次设备号定义帧缓冲的个数,最大允许有32FrameBuffer,定义在/include/linux/fb.h中的FB_MAX,对应于文件系统下/dev/fb%d设备文件,使用如下方式(前面的数字表示次设备号):
      0 = /dev/fb0 第一个fb 设备
      1 = /dev/fb1 第二个fb 设备

fb 也是一种普通的内存设备,可以像内存设备(/dev/mem)一样,对其read,write,seek 以及mmap。但区别在于fb 使用的不是整个内存区,而是显存部分。

典型的显示机制如图所示:

fb与应用程序的交互 

对于用户程序而言,它和其他的设备并没有什么区别,用户可以把fb看成是一块内存,既可以向内存中写数据,也可以读数据。fb的显示缓冲区位于内核空间,应用程序可以把此空间映射到自己的用户空间,在进行操作。

(1)    在应用程序中,操作/dev/fbn的一般步骤如下:
打开/dev/fbn设备文件。

(2)    ioctl()操作取得当前显示屏幕的参数,如屏幕分辨率、每个像素点的比特数。根据屏幕参数可计算屏幕缓冲区的大小。

(3)    mmap()函数,将屏幕缓冲区映射到用户空间。

(4)    映射后就可以直接读/写屏幕缓冲区,进行绘图和图片显示了。

(5)    使用完帧缓冲设备后需要将其释放。

(6)    关闭文件。

 

fb的控制

ioctl来用各种命令控制fb,控制的实现都定义在中。这个头文件是内核源码中的,由于交叉编译器中将其包含了,所以我们可以在应用层直接调用。

,里面定义了一些ioctl的命令

/* ioctls

   0x46 is 'F'                              */

#define FBIOGET_VSCREENINFO 0x4600

#define FBIOPUT_VSCREENINFO 0x4601

#define FBIOGET_FSCREENINFO 0x4602

#define FBIOGETCMAP     0x4604

#define FBIOPUTCMAP     0x4605

#define FBIOPAN_DISPLAY     0x4606

我们主要使用FBIOGET_VSCREENINFOFBIOGET_FSCREENINFO 命令。从字面意思我们不难看出,这两个命令的意思分别为

fb’s ioctl, to get variable screen info:获取应用程序可改变的参数(如设定的分辨率)

fb’s ioctl, to get fixed screen info:获取固定的参数(如屏幕的分辨率,一般只是拿来看看)

中还提供了专门的结构体类型,用来存放上述两个参数。

存放可变参数的结构体类型:struct fb_var_screeninfo,其详细定义参照“相关结构体”部分。

比较重要的可变参数有:

xresyres:可视画面的xy轴分辨率(应用层改不了)

xres_virtualyres_virtual:虚拟画面(即fbxy轴分辨率

xoffsetyoffset:可视画面相对于虚拟画面的xy轴偏移量

bits_per_pixel:像素深度

虚拟画面一般会被默认设为(不一定的)可视画面的两倍,这种结构被称之为“双缓冲机制”,这样做的好处是可以一边显示,一边缓冲下一幅画面 。

 

相关结构体

相关结构体及其关系为:

 

fb_var_screeninfo

这个结构描述了显示卡的特性。


	

点击(此处)折叠或打开

  1. struct fb_var_screeninfo
  2. {
  3.     __u32 xres; /* visible resolution */
  4.     __u32 yres;
  5.     __u32 xres_virtual; /* virtual resolution */
  6.     __u32 yres_virtual;
  7.     __u32 xoffset; /* offset from virtual to visible resolution */
  8.     __u32 yoffset;
  9.     __u32 bits_per_pixel; /* guess what */
  10.     __u32 grayscale; /* != 0 Gray levels instead of colors */
  11.     struct fb_bitfield red; /* bitfield in fb mem if true color, */
  12.     struct fb_bitfield green; /* else only length is significant */
  13.     struct fb_bitfield blue;
  14.     struct fb_bitfield transp; /* transparency */
  15.     __u32 nonstd; /* != 0 Non standard pixel format */
  16.     __u32 activate; /* see FB_ACTIVATE_* */
  17.     __u32 height; /* height of picture in mm */
  18.     __u32 width; /* width of picture in mm */
  19.     __u32 accel_flags; /* acceleration flags (hints) */
  20.     /* Timing: All values in pixclocks, except pixclock (of course) */
  21.     __u32 pixclock; /* pixel clock in ps (pico seconds) */
  22.     __u32 left_margin; /* time from sync to picture */
  23.     __u32 right_margin; /* time from picture to sync */
  24.     __u32 upper_margin; /* time from sync to picture */
  25.     __u32 lower_margin;
  26.     __u32 hsync_len; /* length of horizontal sync */
  27.     __u32 vsync_len; /* length of vertical sync */
  28.     __u32 sync; /* see FB_SYNC_* */
  29.     __u32 vmode; /* see FB_VMODE_* */
  30.     __u32 reserved[6]; /* Reserved for future compatibility */
  31. };

fb_fix_screeninfon

这个结构在显卡被设定模式后创建,它描述显示卡的属性,并且系统运行时不能被修改;比如FrameBuffer内存的起始地址。它依赖于被设定的模式,当一个模 式被设定后,内存信息由显示卡硬件给出,内存的位置等信息就不可以修改。


点击(此处)折叠或打开

  1. struct fb_fix_screeninfo {
  2.     char id[16]; /* identification string eg "TT Builtin" */
  3.     unsigned long smem_start; /* Start of frame buffer mem */
  4.     /* (physical address) */
  5.     __u32 smem_len; /* Length of frame buffer mem */
  6.     __u32 type; /* see FB_TYPE_* */
  7.     __u32 type_aux; /* Interleave for interleaved Planes */
  8.     __u32 visual; /* see FB_VISUAL_* */
  9.     __u16 xpanstep; /* zero if no hardware panning */
  10.     __u16 ypanstep; /* zero if no hardware panning */
  11.     __u16 ywrapstep; /* zero if no hardware ywrap */
  12.     __u32 line_length; /* length of a line in bytes */
  13.     unsigned long mmio_start; /* Start of Memory Mapped I/O */
  14.     /* (physical address) */
  15.     __u32 mmio_len; /* Length of Memory Mapped I/O */
  16.     __u32 accel; /* Type of acceleration available */
  17.     __u16 reserved[3]; /* Reserved for future compatibility */
  18. };

fb_ops

用户应用可以使用ioctl()系统调用来操作设备,这个结构就是用以支持ioctl()的这些操作的。

点击(此处)折叠或打开

  1. struct fb_ops {
  2. /* open/release and usage marking */
  3. struct module *owner;
  4. int (*fb_open)(struct fb_info *info, int user);
  5. int (*fb_release)(struct fb_info *info, int user);
  6. /* get non settable parameters */
  7. int (*fb_get_fix)(struct fb_fix_screeninfo *fix, int con,
  8. struct fb_info *info);
  9. /* get settable parameters */
  10. int (*fb_get_var)(struct fb_var_screeninfo *var, int con,
  11. struct fb_info *info);
  12. /* set settable parameters */
  13. int (*fb_set_var)(struct fb_var_screeninfo *var, int con,
  14. struct fb_info *info);
  15. /* get colormap */
  16. int (*fb_get_cmap)(struct fb_cmap *cmap, int kspc, int con,
  17. struct fb_info *info);
  18. /* set colormap */
  19. int (*fb_set_cmap)(struct fb_cmap *cmap, int kspc, int con,
  20. struct fb_info *info);
  21. /* pan display (optional) */
  22. int (*fb_pan_display)(struct fb_var_screeninfo *var, int con,
  23. struct fb_info *info);
  24. /* perform fb specific ioctl (optional) */
  25. int (*fb_ioctl)(struct inode *inode, struct file *file, unsigned int cmd,
  26. unsigned long arg, int con, struct fb_info *info);
  27. /* perform fb specific mmap */
  28. int (*fb_mmap)(struct fb_info *info, struct file *file, struct
  29. vm_area_struct *vma);
  30. /* switch to/from raster image mode */
  31. int (*fb_rasterimg)(struct fb_info *info, int start);
  32. };

fb_cmap

描述设备无关的颜色映射信息。可以通过FBIOGETCMAP FBIOPUTCMAP 对应的ioctl操作设定或获取颜色映射信息。

点击(此处)折叠或打开

  1. struct fb_cmap {
  2. __u32 start; /* First entry */
  3. __u32 len; /* Number of entries */
  4. __u16 *red; /* Red values */
  5. __u16 *green;
  6. __u16 *blue;
  7. __u16 *transp; /* transparency, can be NULL */
  8. }


fb_info

定义当显卡的当前状态;fb_info结构仅在内核中可见,在这个结构中有一个fb_ops指针,指向驱动设备工作所需的函数集。

点击(此处)折叠或打开

  1. struct fb_info {
  2. char modename[40]; /* default video mode */
  3. kdev_t node;
  4. int flags;
  5. int open; /* Has this been open already ? */
  6. #define FBINFO_FLAG_MODULE 1 /* Low-level driver is a module */
  7. struct fb_var_screeninfo var; /* Current var */
  8. struct fb_fix_screeninfo fix; /* Current fix */
  9. struct fb_monspecs monspecs; /* Current Monitor specs */
  10. struct fb_cmap cmap; /* Current cmap */
  11. struct fb_ops *fbops;
  12. char *screen_base; /* Virtual address */
  13. struct display *disp; /* initial display variable */
  14. struct vc_data *display_fg; /* Console visible on this display */
  15. char fontname[40]; /* default font name */
  16. devfs_handle_t devfs_handle; /* Devfs handle for new name */
  17. devfs_handle_t devfs_lhandle; /* Devfs handle for compat. symlink */
  18. int (*changevar)(int); /* tell console var has changed */
  19. int (*switch_con)(int, struct fb_info*);
  20. /* tell fb to switch consoles */
  21. int (*updatevar)(int, struct fb_info*);
  22. /* tell fb to update the vars */
  23. void (*blank)(int, struct fb_info*); /* tell fb to (un)blank the screen */
  24. /* arg = 0: unblank */
  25. /* arg > 0: VESA level (arg-1) */
  26. void *pseudo_palette; /* Fake palette of 16 colors and
  27. the cursor's color for non
  28. palette mode */
  29. /* From here on everything is device dependent */
  30. void *par;
  31. };


使用实例


点击(此处)折叠或打开

  1. #include <stdio.h>
  2. #include <sys/stat.h>
  3. #include <sys/types.h>
  4. #include <sys/ioctl.h>
  5. #include <fcntl.h>
  6. #include <linux/fb.h>
  7. #include <sys/mman.h>
  8. #include <stdlib.h>
  9. #include <unistd.h>

  10. #define FBDEVICE "/dev/fb0"
  11. void draw_back(unsigned int *pfb, unsigned int width, unsigned int height, unsigned int color);

  12. void draw_line(unsigned int *pfb, unsigned int width, unsigned int height);

  13. int main(void)
  14. {
  15.     int fd = -1;
  16.     int ret = -1;
  17.     unsigned int *pfb = NULL;
  18.     struct fb_fix_screeninfo finfo;
  19.     struct fb_var_screeninfo vinfo;

  20.     fd = open(FBDEVICE, O_RDWR);
  21.     if (fd < 0)
  22.     {
  23.         perror("open");
  24.         return -1;
  25.     }
  26.     printf("open %s success \n", FBDEVICE);

  27.    
  28.     ret = ioctl(fd, FBIOGET_FSCREENINFO, &finfo);
  29.     if (ret < 0)
  30.     {
  31.         perror("ioctl");
  32.         return -1;
  33.     }

  34.     ret = ioctl(fd, FBIOGET_VSCREENINFO, &vinfo);
  35.     if (ret < 0)
  36.     {
  37.         perror("ioctl");
  38.         return -1;
  39.     }
  40.     
  41.     pfb = (unsigned int *)mmap(NULL, finfo.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
  42.     if (NULL == pfb)
  43.     {
  44.         perror("mmap");
  45.         return -1;
  46.     }
  47.     printf("pfb :0x%x \n", *pfb);

  48.     draw_back(pfb, vinfo.xres_virtual, vinfo.yres_virtual, 0xffff0000);
  49.     draw_line(pfb, vinfo.xres_virtual, vinfo.yres_virtual);

  50.     close(fd);
  51.     return 0;
  52. }


  53. void draw_back(unsigned int *pfb, unsigned int width, unsigned int height, unsigned int color)
  54. {
  55.     unsigned int x, y;
  56.     for (y = 0; y < height; y++)
  57.     {
  58.         for (x = 0; x < width; x++)
  59.         {
  60.             *(pfb + y * width + x) = color;
  61.         }
  62.     }
  63. }

  64. void draw_line(unsigned int *pfb, unsigned int width, unsigned int height)
  65. {
  66.     unsigned int x, y;
  67.     for (x = 50; x < width - 50; x++)
  68.     {
  69.         *(pfb + 50 * width + x) = 0xffffff00;
  70.     }
  71.     for (y = 50; y < height -50; y++)
  72.     {
  73.         *(pfb + y * width + 50) = 0xffffff00;
  74.     }
  75. }


 

厚积薄发,不负年华。