帧缓冲(framebuffer)是Linux为显示设备提供的一个接口,把显存抽象后的一种设备,他允许上层应用程序在图形模式下直接对显示缓冲区进行读写操作。这种操作是抽象的,统一的。用户不必关心物理显存的位置、换页机制等等具体细节。这些都是由Framebuffer设备驱动来完成的。
帧缓冲驱动的应用广泛,在linux的桌面系统中,Xwindow服务器就是利用帧缓冲进行窗口的绘制。尤其是通过帧缓冲可显示汉字点阵,成为Linux汉化的唯一可行方案。
Linux FrameBuffer 本质上只是提供了对图形设备的硬件抽象,在开发者看来,FrameBuffer 是一块显示缓存,往显示缓存中写入特定格式的数据就意味着向屏幕输出内容。所以说FrameBuffer就是一块白板。例如对于初始化为16 位色的FrameBuffer 来说, FrameBuffer中的两个字节代表屏幕上一个点,从上到下,从左至右,屏幕位置与内存地址是顺序的线性关系。
帧缓存可以在系统存储器(内存)的任意位置,视频控制器通过访问帧缓存来刷新屏幕。 帧缓存也叫刷新缓存 Frame buffer 或 refresh buffer, 这里的帧(frame)是指整个屏幕范围。
帧缓存有个地址,是在内存里。我们通过不停的向frame buffer中写入数据, 显示控制器就自动的从frame buffer中取数据并显示出来。全部的图形都共享内存中同一个帧缓存。
-------
以上内容摘自百度百科
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <stdlib.h>
#define FB_PATH "/dev/fb0" /*帧缓冲设备在linux系统中对应的设备文件*/
#define IMG_LENGTH 800*600*4
#include <sys/types.h>
#include <sys/stat.h>
/*************************************************
Function: init_fb
Description: 打开帧缓冲设备,获得帧缓冲设备固定结构体数据和可变结构体数据,设置映射
Input: 帧缓冲设备的设备文件位置
Output: 标识帧缓冲设备的文件描述符
Return: 帧缓冲设备映射后的起始地址
Others:
*************************************************/
char *init_fb(char *fbpath, int *fbfd)
{
*fbfd = open(fbpath, O_RDWR);
if(*fbfd < 0)
{
perror("open frambuffer device failed!");
return (char *)-1;
}
struct fb_var_screeninfo vinfo;
struct fb_fix_screeninfo finfo;
if (ioctl(*fbfd,FBIOGET_FSCREENINFO,&finfo))
{
perror("reading fixed information failed");
return (char *)-1;
}
if (ioctl(*fbfd,FBIOGET_VSCREENINFO,&vinfo))
{
perror("reading variable information failed");
return (char *)-1;
}
/* struct fb_var_screeninfo 和 struct fb_fix_screeninfo 兩个数据结构是在/usr/include/linux/fb.h中定义的,
它们都是无符号32位的整数
在fb_fix_screeninfo中有
__u32 smem_len 是這个/dev/fb0的大小,也就是內存大小。
__u32 line_length 是屏幕上一行的点在內存中占有的空间(即字节数),不是一行上的点数。
在fb_var_screeninfo 中有
__u32 xres ,__u32 yres 是x和y方向的分辨率,就是兩個方向上的点数。
__u32 bits_per_pixel 是每一点占有的內存空间。 */
unsigned int screensize = vinfo.xres_virtual * vinfo.yres_virtual * vinfo.bits_per_pixel / 8;
//unsigned int screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
printf("-----------------------------------------\n");
printf("The mem is :%d\n",finfo.smem_len);
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);
printf("the screensize is %d\n", screensize);
printf("-----------------------------------------\n");
/*帧缓冲设备的内存位于内核空间,需要用mmap将其映射到用户空间(提高访问速度)*/
char *fbp = (char *)mmap(NULL, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, *fbfd, 0);
if(fbp == (char *)-1)
{
perror("map framebuffer device to usr memory failed");
return (char *)-1;
}
return fbp;
}
/*************************************************
Function: write_data_to_fb
Description: 向帧缓冲设备写入数据
Input:fbp(缓冲区起始地址);fbfd(标识缓冲区的文件描述符);img_buf(存放图片数据的缓冲区)
img_width(图片数据的宽); img_height(图片数据的高);img_bits(图片数据的位深度)
Output: 无
Return: int(成功返回0, 失败返回 -1)
Others: 用于向缓冲区打印图片
*************************************************/
int write_data_to_fb(char *fbp, int fbfd, char *img_buf, unsigned int img_width, unsigned int img_height, unsigned int img_bits)
{
struct fb_var_screeninfo vinfo;
if (ioctl(fbfd,FBIOGET_VSCREENINFO,&vinfo))
{
perror("reading variable information failed");
return -1;
}
struct fb_fix_screeninfo finfo;
if (ioctl(fbfd,FBIOGET_FSCREENINFO,&finfo))
{
perror("reading fixed information failed");
return -1;
}
unsigned int screensize = vinfo.xres_virtual * vinfo.yres_virtual * vinfo.bits_per_pixel / 8;
//unsigned int screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
int row, column;
int num = 0; //img_buf 中的某个字节元素对应下标
/*直接打印出来的图片是倒着的,需要反着打印*/
for(row = img_height - 1; row>=0; row--)
{
for(column = 0; column< img_width * img_bits / 8; column++)
{
fbp[row * finfo.line_length+column] = img_buf[num];/*
finfo.line_length为帧缓冲设备每一行所占字节数
finfo.line_length * row+column为帧缓冲设备第finfo.line_length * row行
第column个字节开始赋值。
*/
num++;
}
//fbp += (vinfo.xres_virtual - img_width)*img_bits / 8;/*屏幕每行所占字节是固定的,不是随图片变化的,不能使用此句*/
//fbp += finfo.line_length - img_width*img_bits / 8; /*finfo.line_length指屏幕每行所占字节数*/
}
return 0;
}
/*test
环境:ubuntu12.04 32位(运行在vmware-workstation虚拟机中)
帧缓冲设备:显示器
test.bmp为测试bmp图片文件,分辨率为800 * 600,32位深度。
为了看到演示效果,请在纯字符界面下操作(ctrl+alt+F1)
*/
#if 1
void main()
{
int fbfd = 0;
char img_buf[IMG_LENGTH];
char * fbp = init_fb(FB_PATH, &fbfd);
struct stat filestatus;
int ret = stat("test.bmp", &filestatus);
if(ret < 0)
{
perror("get file stat failed!");
return;
}
int imgsize = filestatus.st_size;
printf("img size is%d\n", imgsize);
FILE *imgfp = fopen("test.bmp","r");
if(imgfp < 0)
{
perror("open test.bmp failed!");
return;
}
if (fread(img_buf, imgsize, 1, imgfp) < 0)
{
printf("read test3.bmp data error!\n");
}
fclose(t);
write_data_to_fb(fbp, fbfd, img_buf+54, 800, 600, 32);
fclose(imgfp);
}
#endif