framebuffer:
即帧缓冲,是计算机图形系统中的一个核心概念,主要用于存储和管理输出到显示器的像素数据。
定义与功能
- 定义:Framebuffer是一个内存区域,用于保存在计算机图形渲染中生成的图像。它是Linux为显示设备提供的一个接口,把显存抽象后的一种设备,允许上层应用程序在图形模式下直接对显示缓冲区进行读写操作。
- 功能:通过提供一块内存区域来存储和管理输出到显示器的像素数据,实现了图形显示的各类功能。
使用方法:
1.打开显示设备。
2.获取显示设备相关参数(分辨率 位深度)。
3.建立内存映射
4.写入RGB颜色值
5.解除映射
6.关闭显示器
组成与特性
- 颜色缓冲区:存储每个像素的颜色信息,如RGBA等。
- 深度缓冲区:存储每个像素的深度信息,用于处理3D场景的遮挡问题。
- 模板缓冲区:用于实现图形遮罩技术,控制哪些像素可以被绘制。
- 多重采样缓冲区(MSAA):用于减少锯齿状边缘的效果,提高图像质量。
应用场景
- 在Linux的桌面系统中,Xwindow服务器利用Framebuffer进行窗口的绘制。
- 通过Framebuffer可显示汉字点阵,成为Linux汉化的可行方案。
- 在游戏和图形密集型应用中,Framebuffer能有效管理和更新图像,提高帧率。
Framebuffer的优点
- 高效渲染:通过将屏幕显示映射到帧缓冲区,Framebuffer能够高效地渲染图形,提高图形渲染效率。这对于需要高质量图形输出的应用,如游戏和多媒体,尤为重要。
- 跨平台性:Framebuffer作为一种低级的通用设备,能够跨平台工作,支持多种硬件平台,如x86、PPC、m68k和SPARC等,甚至在嵌入式设备上也能正常工作。
- 简化图形编程:Framebuffer为上层软件提供了一个良好定义的软件接口,使其能够访问图形硬件,而无需关心底层硬件的具体实现细节。这大大简化了图形编程的复杂性,使得开发者可以更加专注于应用程序的逻辑实现。
- 支持离屏渲染:Framebuffer支持离屏渲染,即可以在屏幕外的缓冲区中进行图形处理,然后再将处理结果复制到屏幕上。这种方式提高了图形处理的性能,并允许更复杂的图形操作。
- 灵活性高:Framebuffer允许应用程序直接控制屏幕显示内容,提供了高度的灵活性。开发者可以根据需要自由修改帧缓冲区中的数据,以实现各种自定义的显示效果。
Framebuffer的缺点
- 内存开销大:由于Framebuffer需要将屏幕输出映射到内存中,因此需要消耗大量的内存。特别是在高分辨率下,内存开销会显著增加,这可能会限制其在内存资源有限的设备上的应用。
- 速度较慢:当实时更新帧缓冲区时,需要花费额外的时间和内存带宽来更新缓冲区。这可能会导致帧率降低、卡顿等问题,影响用户体验。
- 资源占用高:Framebuffer需要大量的处理资源来支持高度定制化的图形渲染和复杂的图形操作。这可能会增加CPU的负担,使得在某些情况下系统响应变慢。
- 对硬件的依赖性强:虽然Framebuffer提供了一种跨平台的解决方案,但其性能和效果仍然受到底层硬件的制约。不同的硬件平台可能需要不同的驱动和配置才能充分发挥Framebuffer的性能。
- 编程复杂度高:虽然Framebuffer简化了图形编程的复杂性,但开发者仍然需要了解相关硬件知识以进行高效编程。特别是对于需要优化性能的应用来说,开发者需要深入了解底层硬件的特性和限制。
注意事项
- Framebuffer中的数据是实时的,如果不捕获,每一帧都会被丢弃。
- Framebuffer可以位于显存或内存,其位置由系统配置和驱动程序决定。
- 在使用Framebuffer时,需要注意不同平台和设备的兼容性问题。
#include "framebuffer.h"
#include <stdio.h>
#include <linux/fb.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <math.h>
void *pmem;
struct fb_var_screeninfo vinf;
int init_fb(char *devname)
{
//1.打开显示设备
int fd = open (devname,O_RDWR);
if(-1 == fd)
{
perror("open fail");
return -1;
}
//2.获取显示设备相关参数 分辨率 位深度
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;
//3.建立显存和用户空间的映射关系
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 = (unsigned int *)pmem;
*( p + y *vinf.xres_virtual +x) = col;
}
else if(vinf.bits_per_pixel == RGB565_FMT)
{
unsigned short *p = (unsigned short *)pmem;
*( p + y * vinf.xres_virtual +x) = col;
}
return ;
}
//画直线
void draw_X_line(int x,int y,int len ,unsigned int col)
{
if(x >= vinf.xres||y >= vinf.yres)
{
return;
}
for(int i = x;i < x+len ;++i)
{
draw_point(i,y,col);
}
}
//画竖线
void draw_Y_line(int x,int y,int len,unsigned int col)
{
if(x >= vinf.xres||y >= vinf.yres)
{
return;
}
for(int i = y;i<y+len;++i)
{
draw_point(x,i,col);
}
}
//画矩形
void draw_rectangle(int x,int y,int len,int wind,unsigned int col)
{
if(x>=vinf.xres||y>= vinf.yres||x+len>=vinf.xres||y+wind>= vinf.yres)
{
return ;
}
draw_X_line(x,y,len,col);
draw_Y_line(x,y,wind,col);
draw_Y_line(x+len,y,wind,col);
draw_X_line(x,y+wind,len,col);
}
//画斜线
void draw_bias(int x1,int y1,int x2,int y2,unsigned int col)
{
float dx = x2-x1;
float dy = y2-y1;
for(int i = 0;i < x2 - x1;++i)
{
int h = (dx - i)*(dy/dx);
draw_point(x1+i,y2 - h,col);
}
}
//画圆
void draw_circle(int x,int y,int r,unsigned int col)
{
for(int i = 0;i<360;++i)
{
int a = x+r *cos(i/180.0 *PI);
int b = y+r *sin(i/180.0 *PI);
draw_point(a,b,col);
}
}
//清屏
void clear_interface()
{
int x = 0;
int y = 0;
for(x = 0;x<=vinf.xres;++x)
{
for(y = 0;y<=vinf.yres;++y)
{
draw_point(x,y,0x00ffffff);
}
}
}
//关闭显示
void uninit_fb(int fd)
{
size_t len = vinf.xres_virtual *vinf.yres_virtual *vinf.bits_per_pixel/8;
munmap(pmem,len);
close(fd);
}