帧缓冲设备编程

帧缓冲(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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值