帧缓冲(framebuffer)是Linux为显示设备提供的一个接口,把显存抽象后的一种设备,他允许上层应用程序在图形模式下直接对显示缓冲区进行
读写操作。framebuffer是LCD对应的一中HAL(硬件抽象层),提供抽象的,统一的接口操作,用户不必关心硬件层是怎么实施的。这些都是由
Framebuffer设备驱动来完成的。
帧缓冲设备对应的设备文件为/dev/fb*,如果系统有多个显示卡,Linux下还可支持多个帧缓冲设备,最多可达32个,分别为/dev/fb0到
/dev/fb31,而/dev/fb则为当前缺省的帧缓冲设备,通常指向/dev/fb0,在嵌入式系统中支持一个显示设备就够了。帧缓冲设备为标准字
符设备,主设备号为29,次设备号则从0到31。分别对应/dev/fb0-/dev/fb31。
通过/dev/fb,应用程序的操作主要有这几种:
1. 读/写(read/write)/dev/fb:相当于读/写屏幕缓冲区。
2.
映射(map)操作:由于Linux工作在保护模式,每个应用程序都有自己的虚拟地址空间,在应用程序中是不能直接访问物理缓冲区地址的。而帧缓冲设备可
以通过mmap()映射操作将屏幕缓冲区的物理地址映射到用户空间的一段虚拟地址上,然后用户就可以通过读写这段虚拟地址访问屏幕缓冲区,在屏幕上绘图
了。
3. I/O控制:对于帧缓冲设备,对设备文件的ioctl操作可读取/设置显示设备及屏幕的参数,如分辨率,屏幕大小等相关参数。ioctl的操作是由底层的驱动程序来完成的。
在应用程序中,操作/dev/fb的一般步骤如下:
1. 打开/dev/fb设备文件。
2. 用ioctl操作取得当前显示屏幕的参数,根据屏幕参数可计算屏幕缓冲区的大小。
3. 将屏幕缓冲区映射到用户空间。
4. 映射后即可直接读写屏幕缓冲区,进行绘图和图片显示。
framebuffer相关数据结构介绍
1. fb_info结构体:帧缓冲设备中最重要的数据结构体,包括了帧缓冲设备属性和操作的完整性属性。
2. fb_ops结构体:fb_info结构体的成员变量,fb_ops为指向底层操作的函数的指针。
3.fb_var_screen和fb_fix_screen结构体:fb_var_screen记录用户可以修改的显示控制器参数,fb_fix_screen记录用户不能修改的显示控制器参数。
以下代码使用framebuffer显示一张图片:
-
#include
-
#include
-
#include
-
#include
-
#include
-
#include
-
#include
-
#include
-
#include
-
-
-
-
typedef struct
-
{
-
char cfType[2];
-
long cfSize;
-
long cfReserved;
-
long cfoffBits;
-
}__attribute__((packed)) BITMAPFILEHEADER;
-
-
-
-
typedef struct
-
{
-
char ciSize[4];
-
long ciWidth;
-
long ciHeight;
-
char ciPlanes[2];
-
int ciBitCount;
-
char ciCompress[4];
-
char ciSizeImage[4];
-
char ciXPelsPerMeter[4];
-
char ciYPelsPerMeter[4];
-
char ciClrUsed[4];
-
char ciClrImportant[4];
-
}__attribute__((packed)) BITMAPINFOHEADER;
-
-
typedef struct
-
{
-
unsigned short blue;
-
unsigned short green;
-
unsigned short red;
-
unsigned short reserved;
-
}__attribute__((packed)) PIXEL;
-
-
BITMAPFILEHEADER FileHead;
-
BITMAPINFOHEADER InfoHead;
-
-
static char *fbp = 0;
-
static int xres = 0;
-
static int yres = 0;
-
static int bits_per_pixel = 0;
-
-
int show_bmp();
-
-
int main ( int argc, char *argv[] )
-
{
-
int fbfd = 0;
-
struct fb_var_screeninfo vinfo;
-
struct fb_fix_screeninfo finfo;
-
long int screensize = 0;
-
struct fb_bitfield red;
-
struct fb_bitfield green;
-
struct fb_bitfield blue;
-
-
-
fbfd = open("/dev/fb0", O_RDWR);
-
if (!fbfd)
-
{
-
printf("Error: cannot open framebuffer device.\n");
-
exit(1);
-
}
-
-
if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo))
-
{
-
printf("Error:reading fixed information.\n");
-
exit(2);
-
}
-
-
if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo))
-
{
-
printf("Error: reading variable information.\n");
-
exit(3);
-
}
-
-
printf("R:%d,G:%d,B:%d \n", vinfo.red, vinfo.green, vinfo.blue );
-
-
printf("%dx%d, %dbpp\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel );
-
xres = vinfo.xres;
-
yres = vinfo.yres;
-
bits_per_pixel = vinfo.bits_per_pixel;
-
-
-
screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
-
printf("screensize=%d byte\n",screensize);
-
-
-
fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);
-
if ((int)fbp == -1)
-
{
-
printf("Error: failed to map framebuffer device to memory.\n");
-
exit(4);
-
}
-
-
printf("sizeof file header=%d\n", sizeof(BITMAPFILEHEADER));
-
-
printf("into show_bmp function\n");
-
-
-
show_bmp();
-
-
-
munmap(fbp, screensize);
-
close(fbfd);
-
return 0;
-
}
-
-
int show_bmp()
-
{
-
FILE *fp;
-
int rc;
-
int line_x, line_y;
-
long int location = 0, BytesPerLine = 0;
-
char tmp[1024*10];
-
-
fp = fopen( "./niu.bmp", "rb" );
-
if (fp == NULL)
-
{
-
return( -1 );
-
}
-
-
rc = fread( &FileHead, sizeof(BITMAPFILEHEADER),1, fp );
-
if ( rc != 1)
-
{
-
printf("read header error!\n");
-
fclose( fp );
-
return( -2 );
-
}
-
-
-
if (memcmp(FileHead.cfType, "BM", 2) != 0)
-
{
-
printf("it's not a BMP file\n");
-
fclose( fp );
-
return( -3 );
-
}
-
-
rc = fread( (char *)&InfoHead, sizeof(BITMAPINFOHEADER),1, fp );
-
if ( rc != 1)
-
{
-
printf("read infoheader error!\n");
-
fclose( fp );
-
return( -4 );
-
}
-
-
-
fseek(fp, FileHead.cfoffBits, SEEK_SET);
-
-
BytesPerLine = (InfoHead.ciWidth * InfoHead.ciBitCount + 31) / 32 * 4;
-
-
line_x = line_y = 0;
-
-
while(!feof(fp))
-
{
-
PIXEL pix;
-
unsigned short int tmp;
-
rc = fread( (char *)&pix, 1, sizeof(PIXEL), fp);
-
if (rc != sizeof(PIXEL))
-
break;
-
location = line_x * bits_per_pixel / 8 + (InfoHead.ciHeight - line_y - 1) * xres * bits_per_pixel / 8;
-
-
-
*(fbp + location + 0)=pix.blue;
-
*(fbp + location + 1)=pix.green;
-
*(fbp + location + 2)=pix.red;
-
*(fbp + location + 3)=pix.reserved;
-
-
line_x++;
-
if (line_x == InfoHead.ciWidth )
-
{
-
line_x = 0;
-
line_y++;
-
if(line_y == InfoHead.ciHeight)
-
break;
-
}
-
}
-
fclose( fp );
-
return( 0 );
-
}
注意:上面的程序只在framebuffer上显示图片,却没有删除刷新屏幕,可以使用下面的命令恢复屏幕
保存屏幕信息:dd if=/dev/fb0 of=fbfile 或: cp /dev/fb0 fbfile
恢复屏幕信息:dd if=fbfile of=/dev/fb0 或: cat fbfile > /dev/fb0
阅读(1036) | 评论(0) | 转发(1) |