Linux Frame Buffer
帧缓冲设备是对具体的图像硬件的一个抽象,它让上层图像应用不必关心具体的硬件实现细节。
分辨率
像素点:pixel显示某种颜色的点
LCD显示原理:
屏由y行且每行x个像素点的矩阵组成;在屏幕上显示图像,就是给每个像素点显示一种颜色。
颜色值,可以量化。
于是,有人就提出在内存中( 显存)开辟一段空间,用来保存屏幕上像素点的颜色值,然后操作
屏幕就直接操作这段内存就可以了,这就是我们说的帧缓冲(frame buffer)
帧缓冲设备操作流程 (fb_test.c)
1.打开设备
2.屏幕信息
3.map
4.作显存
5.nmap
6.close
具体操作:
内核提供给应用的除了读或写以外其他控制设备的操作接口。每个设备的控制操作不一样,所以该函数的参数由写这个设备驱动的人确定。
操作的函数: ioctl
int ioctl(int fd, int request, …);
fd:文件描述符。表示你要操作哪个设备。
request:一般表示一个命令号。该命令号由驱动开发者提供。
… :其他参数,不同的命令可能有不同的参数。
所以这个参数也是驱动开发者提供。
返回值:
如果成功返回0,
失败返回 -1
//struct fb_bitfield 用来表示颜色分量的具体占多少bit,
//起始位置在哪里
struct fb_bitfield {
__u32 offset; //起始bit 的偏移量
__u32 length; //颜色分量的长度(多少bits)
__u32 msb_right; //颜色分量的最高位是否在右边
//非0,表示在右边
};
struct fb_var_screeninfo {
__u32 xres; //屏幕分辨率 长
__u32 yres; //屏幕分辨率 高
__u32 bits_per_pixel; //每个像素点占多少bit
//每种颜色都是由R G B三个分量组成的。
//以下几个成员变量是表示,一个像素点中,
//RGB三个分量分别占多少bit, 开始位置在哪里。
//还有一个transp是表示透明度的意思。
//ARGB
struct fb_bitfield red;
struct fb_bitfield green;
struct fb_bitfield blue;
struct fb_bitfield transp;
//.....
};
在屏幕上显示一张图片代码:
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include "image.h"
char *plcd = NULL;//
/*
LCD_DrawPoint在屏幕位置<x,y>上,显示color这种颜色值*/
void LCD_DrawPoint(unsigned long x, unsigned long y, int color)
{
int * p = (int *)plcd;
*(p + y*800 + x) = color;
}
/*
给屏幕上每一个像素点都显示color这种颜色值
*/
void LCD_ClearSrc(int color)
{
int x, y;
for (y = 0; y < 480; y++)
{
for (x = 0; x < 800; x++)
{
LCD_DrawPoint(x, y, color);
}
}
}
/*
24bits BGR
=> B G R A
*/
void LCD_DrawBmp(const unsigned char gImage_bmp[])
//gImage_bup[] 数组是用软件生成的一个数组,就是让每一点有一个颜色。RGBA
{
int pixels = 800 * 480 ;
int i, j = 0;
char *p = plcd;
for (i = 0; i < pixels; i++)
{
*p++ = gImage_bmp[j++]; //B
*p++ = gImage_bmp[j++];//G
*p++ = gImage_bmp[j++];//R
*p++ = 0; //A
}
}
int main()
{
int fb;
/*step 1: 打开设备*/
fb = open("/dev/fb0", O_RDWR);
if (fb < 0)
{
perror("open failed:");
return -1;
}
/*step 2: 获取屏幕信息*/
struct fb_var_screeninfo fbinfo;
ioctl(fb, FBIOGET_VSCREENINFO, &fbinfo);
printf("%d * %d * %d\n", fbinfo.xres, fbinfo.yres, fbinfo.bits_per_pixel / 8);
printf("[red]offset: %d length: %d msb_right: %d\n", fbinfo.red.offset, fbinfo.red.length, fbinfo.red.msb_right);
printf("[green]offset: %d length: %d msb_right: %d\n", fbinfo.green.offset, fbinfo.green.length, fbinfo.green.msb_right);
printf("[blue]offset: %d length: %d msb_right: %d\n", fbinfo.blue.offset, fbinfo.blue.length, fbinfo.blue.msb_right);
/*step 3: mmap*/
plcd = mmap(NULL, fbinfo.xres * fbinfo.yres *(fbinfo.bits_per_pixel/8), PROT_WRITE, MAP_SHARED, fb, 0);
if (plcd == MAP_FAILED)
{
perror("mmap failed:");
return -1;
}
/*step 4: 操作屏幕*/
//memset(plcd, 0x88 ,fbinfo.xres * fbinfo.yres *(fbinfo.bits_per_pixel/8));
//LCD_ClearSrc(0xFF00FF);
LCD_DrawBmp( gImage_image);
munmap(plcd,);
/*step 6: close*/
close(fb);
return 0;
}