一、基本概念
framebuffer: 帧缓存、帧缓存(显示设备)
Linux内核为显示提供的一套应用程序接口。(驱动内核支持)
分辨率:
像素点
显示屏:800 * 600(横向有800个像素点,纵向有600个像素点)
显卡(显存(保存像素点的值))
RGB
888(8个bitR,8个bit G,8个bit B)
PC ,4412(RGB888)
RGB565(S3C2440)
为了提高代码的书写效率(将RGB扩充到4字节)
二、解决显存空间不能直接被用户访问
根据显存的大小的多少,来申请空间
1、打开显示设备(/dev/fb0)
2、获取显示设备相关参数(分辨率、位深度......)
3、建立内存映射
4、写入RGB颜色值
5、解除映射
6、关闭显示设备
三、framebuffer常问话术
framebuff(是什么,具体原理、怎么做、)
是什么:Linux内核为显示提供的一套应用程序接口。(驱动内核支持)
具体原理:通过内存映射技术,向显存空间写入RGB值
1、打开显示设备(/dev/fb0)
2、获取显示设备相关参数(分辨率、位深度......)
3、建立内存映射
4、写入RGB颜色值
5、解除映射
6、关闭显示设备
点线面圆清屏:
#include<stdio.h>
#include "framebuffer.h"
#include <linux/fb.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include<math.h>
void *pmem;
struct fb_var_screeninfo vinf;
int init_fb(char *devname)
{
int fd = open(devname, O_RDWR);
if (-1 == fd)
{
perror("fail open fb");
return -1;
}
int ret = ioctl(fd, FBIOGET_VSCREENINFO, &vinf);
if (-1 ==ret)
{
perror("fail ioctl");
return -1;
}
printf("xres = %d, yres = %d\n", vinf.xres, vinf.yres);
printf("xres_virtual = %d, yres_virtual = %d\n", vinf.xres_virtual, vinf.yres_virtual);
printf("bits_per_pixel : %d\n", vinf.bits_per_pixel);
size_t len = vinf.xres_virtual * vinf.yres_virtual * vinf.bits_per_pixel/8;
pmem = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
if ((void *)-1 == pmem)
{
perror("fail mmap");
return -1;
}
return fd;
}
void draw_point(int x, int y, unsigned int col)
{
if (x >= vinf.xres || y >= vinf.yres)
{
return ;
}
if (vinf.bits_per_pixel == RGB888_FMT)
{
unsigned int *p = pmem;
*(p + y * vinf.xres_virtual + x) = col;
}
else if (vinf.bits_per_pixel == RGB565_FMT)
{
unsigned short *p = pmem;
*(p + y * vinf.xres_virtual + x) = col;
}
return ;
}
void draw_line( int x1, int x2,int y, unsigned int col)
{
for(int i = x1;i < x2;++i)
{
draw_point(i,y,col);
}
}
void draw_pipe(int x, int y1, int y2, unsigned int col)
{
for(int i = y1;i < y2;++i)
{
draw_point(x,i,col);
}
}
void draw_slash(int x1, int y1, unsigned int col,int len)
{
for(int i = 0;i < len;++i)
{
draw_point(x1 + i,y1 + i ,col);
}
}
void uninit_fb(int fd)
{
size_t len = vinf.xres_virtual * vinf.yres_virtual * vinf.bits_per_pixel/8;
munmap(pmem, len);
close(fd);
}
void draw_rectangle(int x,int y,int ab,int ac,unsigned int col)
{
if(x >= vinf.xres || y >= vinf.yres)
{
return;
}
unsigned int *p = (unsigned int *)pmem;
for(int i = 0; i < ab;++i)
{
for(int j = 0;j < ac;++j)
{
*(p + (y + j)* vinf.xres_virtual + x + i) = col;
}
}
return;
}
void draw_circle(int x,int y,int rad,unsigned int col)
{
int a,b;
for(int i = 0;i < 360;++i)
{
a = x + rad * cos( i / 180.0 * 3.14);
b = y + rad * sin( i / 180.0 * 3.14);
draw_point(a,b,col);
}
}
void clean_scren(unsigned int col)
{
for(int i = 0; i < vinf.xres_virtual;++i)
{
for(int j = 0; j < vinf.yres_virtual; ++j)
{
draw_point(i,j,col);
}
}
}
声明:
#ifndef _FRAMEBUFFER_H
#define _FRAMEBUFFER_H
#define RGB888_FMT 32
#define RGB565_FMT 16
extern int init_fb(char *devname);
extern void draw_point(int x,int y, unsigned int col);
extern void uninit_fb(int fd);
void draw_line(int x1, int x2,int y, unsigned int col);
void draw_pipe(int x, int y1, int y2, unsigned int col);
void draw_slash(int x1,int y1, unsigned int col,int len);
void draw_rectangle(int x,int y,int ab,int ac,unsigned int col);
void draw_circle(int x,int y,int rad,unsigned int col);
void clean_scren(unsigned int col);
#endif
主函数:
#include<stdio.h>
#include "framebuffer.h"
int main(int argc, const char *argv[])
{
int fb_fd = init_fb("/dev/fb0");
if (-1 == fb_fd)
{
return -1;
}
draw_point(400, 300, 0x00ff0000);
draw_line(350,450,300,0x00ff0000);
draw_pipe(400,250,350,0x00ff0000);
draw_slash(400,300,0x00ff0000,350);
draw_rectangle(300,300,100,100,0x00ff0000);
draw_circle(300,300,100,0x00ff0000);
clean_scren(0x00ffffff);
uninit_fb(fb_fd);
return 0;
}
gcc *.c -lm
ctrl + alt + f3进入原始终端
输入用户名密码,sudo ./a.out