什么是framebuffer,怎么应用(一)————如何画点、线、矩形、圆

FrameBuffer,可以译作帧缓存,有时候简称为fbdrv。
这是一种独立于硬件的抽象图形设备。
是Linux为显示设备提供的一个接口,把显存抽象后的一种设备,允许上层应用程序在图形模式下直接对显示缓冲区进行读写操作。

如何控制framebuffer

对于应用层,通过操作/dev/fb*,通过ioctl来用各种命令控制framebuffer
我们可以在**/usr/include/linux/fb.h** 中查看

进入内核源码中看看<linux/fb.h>,里面定义了一些ioctl的命令

#define FBIOGET_VSCREENINFO 0x4600   //获取应用程序可改变的参数(如设定的分辨率)
#define FBIOPUT_VSCREENINFO 0x4601 
#define FBIOGET_FSCREENINFO 0x4602   //获取固定的参数(如屏幕的分辨率,一般只是拿来看看)
#define FBIOGETCMAP     0x4604
#define FBIOPUTCMAP     0x4605
#define FBIOPAN_DISPLAY     0x4606

<linux/fb.h>中还提供了专门的结构体类型,用来存放上述两个参数,如下就是存放可变参数的结构体类型

__u32 xres;         /* visible resolution 可视画面的x、y轴分辨率      */ 
__u32 yres;
__u32 xres_virtual;     /* virtual resolution   虚拟画面的x、y轴分辨率    */
__u32 yres_virtual;
__u32 xoffset;          /* offset from virtual to visible 可视画面相对于虚拟画面的x、y轴偏移量*/
__u32 yoffset;          /* resolution           */

__u32 bits_per_pixel;       /* guess what   像素深度        */
__u32 grayscale;        /* != 0 Graylevels instead of colors */

struct fb_bitfield red;     /* bitfield in fb mem if true color, */
struct fb_bitfield green;   /* else only length is significant */
struct fb_bitfield blue;
struct fb_bitfield transp;  /* transparency         */  

__u32 nonstd;           /* != 0 Non standard pixel format */

__u32 activate;         /* see FB_ACTIVATE_*        */

__u32 height;           /* height of picture in mm    */
__u32 width;            /* width of picture in mm     */

__u32 accel_flags;      /* (OBSOLETE) see fb_info.flags */

#include <sys/mman.h>

在进行帧缓存时,我们首先要进行内存映射,所有就需要用到此头文件#include <sys/mman.h>
首先是mmap函数,其功能是开启内存映射,munmap函数,是解除虚拟内存映射

mmap函数

void *mmap(void *addr, size_t length, int prot, int flags,
                  int fd, off_t offset);
功能:内存映射
参数:
	addr:欲映射内存的起始地址,NULL表示系统自动选定,映射
		  成功后返回该地址
    length:映射内存大小
	prot:映射区域的保护方式(读//执行/不能存取)
	flags:影响区域映射的各种特性
			MAP_SHARED:对映射区域写入的数据会复制回源文件内,
						而且允许其他映射该文件的进程共享
			MAP_PRIVATE:对映射区域的写入操作会产生一个映射文件的复制,
						即对此区域的任何修改都不会写回原来的文件内
	fd:要映射的目标文件
	offset:文件映射的偏移量(0代表从开头开始)
返回值:
    void * :返回映射欲映射内存的首地址
eg:
unsigned int* addr = mmap(NULL, 800*480*4, PROT_READ|PROT_WRITE,MAP_SHARED, fd, 0);

munmap函数

int munmap(void *addr, size_t length);
功能:解除内存映射
参数:
	addr:映射内存的地址
	length:映射内存大小
	
#include <sys/ioctl.h>
	   
int ioctl(int fd, int request, ...);	
   ioctl(fd, FBIOGET_VSCREENINFO, &vinfo);	//获取屏幕信息(可变)

实战

接下来,我用几个例子来演示一下。

头文件

#ifndef _FRAMEBUFFER_H_
#define _FRAMEBUFFER_H_


#define RGB888_FMT 32    //GRB888图像格式
#define RGB565_FMT 16    //GRB565图像格式

/*framebuffer相关参数*/
struct fb
{
	void *pmem;                 //映射的用户空间首地址
	unsigned int bits;          //像素深度(一个像素点颜色值的位数)
	unsigned int x_virtual;     //虚拟显存空间横向分辨率
	unsigned int y_virtual;     //虚拟显存空间纵向分辨率
	int fd;                     //显示设备文件描述符
};

extern int init_fb(const char *fbname);
extern void uninit_fb();
extern void draw_point(int x, int y, unsigned int col);

#endif

初始化显示设备

在开始阶段,我们首先需要进行的操作是,打开**/dev/fb0**(初始化设备)

struct fb fbinfo_g;

//初始化显示设备
int InitFb(const char *fbname)
{
	//打开显示设备,用读写方式
	int fd = open(fbname,O_RDWR);
	if(-1 == fd)	//若打开失败,返回-1
	{
		perror("fail to fb");	//终端显示
		return -1;
	}

	struct fb_var_screeninfo vinf;
	//获取显示设备相关参数:分辨率、像素深度
	int ret = ioctl(fd,FBIOGET_VSCREENINFO,&vinf);
	if(0 > ret)
	{
		perror("fail to ioctl");
		return -1;
	}

	printf("xres = %d,yres = %d\n",vinf.xres,vinf.yres);	//输出可视画面的x、y轴分辨率
	printf("xres_virtual = %d, yres_virtual = %d\n", vinf.xres_virtual, vinf.yres_virtual);	//输出虚拟显存空间x、y轴分辨率
	printf("bits_per_pixel = %d\n", vinf.bits_per_pixel);	//输出像素深度

	//将该值赋值到我们所写framebuffer相关参数的结构体当中
	fbinfo_g.bits = vinf.bits_per_pixel;
	fbinfo_g.x_virtual = vinf.xres_virtual;
	fbinfo_g.y_virtual = vinf.yres_virtual;
	fbinfo_g.fd = fd;

	//建立内存映射关系:将显存空间映射到用户空间
	size_t size = vinf.xres_virtual * vinf.yres_virtual * vinf.bits_per_pixel / 8;	//除以8是因为像素深度单位是位,要将其转化为比特
	fbinfo_g.pmem = mmap(NULL,size,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
	if((void *)-1 == fbinfo_g.pmem)
	{
		perror("fail to mmap");
		return -1;
	}

	return 0;
}

关闭显示设备

//关闭显示设备
void UnInitFb()
{
	munmap(fbinfo_g.pmem,fbinfo_g.x_virtual * fbinfo_g.y_virtual * fbinfo_g.bits / 8);
	close(fbinfo_g.fd);
}

如何画点

//绘制像素点
void DrawPoint(int x,int y,unsigned int col)	//x坐标、y坐标、颜色
{
	if(x >= fbinfo_g.x_virtual || y >= fbinfo_g.y_virtual)	
	{
		return ;	//判断如果已经大于其虚拟显存空间了,直接ruturn
	}
//判断像素格式是888格式还是565格式,888代表r、g、b分别占8位,565类似。
	if(fbinfo_g.bits == RGB888_FMT)	
	{
		unsigned int *p = fbinfo_g.pmem;	//p:映射的用户空间首地址
		*(p + y*fbinfo_g.x_virtual + x) = col;
	}
	else if(fbinfo_g.bits == RGB565_FMT)//RGB565
	{
		unsigned short *p = fbinfo_g.pmem; 
		*(p+y*fbinfo_g.x_virtual + x) = col;
	}
}

结果:

DrawPoint(500,400,0x00ff0000);	
DrawPoint(500,500,0x00ff0000);

在这里插入图片描述
我们可以看到图右下角有两个小红点(有点小)。

如何画线

我们已经学会画点了,那么线就是画一连串的点即可。

//绘制横线
void DrawLine(int x,int y,int len,unsigned int col)	//len表示线的长度
{
	for(int i = x;i < x+len;++i)
	{
		DrawPoint(i,y,col);
	}
}

//绘制纵线
void DrawLongLine(int x,int y,int len,unsigned int col)
{
	for(int i = y;i < y+len;++i)
	{
		DrawPoint(x,i,col);
	}
}

结果:

DrawLine(200,200,200,0x00ff0000);
DrawLongLine(300,300,200,0x00ff0000);

在这里插入图片描述## 怎么画矩形

//绘制矩形
//参数3:宽度	参数4:高度
void DrawRectangle(int x,int y,int w,int h,unsigned int col)	
{
	DrawLine(x,y,w,col);
	DrawLongLine(x,y,h,col);
	DrawLongLine(x+w,y,h,col);
	DrawLine(x,y+h,w,col);
}

结果:

DrawRectangle(100,100,200,300,0x00ff0000);

在这里插入图片描述

如何画圆

//绘制圆
void DrawCircle(int x,int y,int r,int col)	//x、y可以获得中心点,r是半径
{
	for(float si = 0;si <= 360;si += 0.1)
	{
		int x0 = r * cos(2 * 3.1415 / 360 * si) + x;
		int y0 = r * sin(2 * 3.1415 / 360 * si) + y;
		DrawPoint(x0,y0,col);
	}
}

由于该函数运用到了sin、cos,我们需要添加头函数<math.h>,所以在编译时,后缀需要加上

-lm

结果:

DrawCircle(300,400,50,0x00ff0000);

在这里插入图片描述
以上就是今天内容,谢谢大家

  • 20
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Framebuffer应用是指在Linux系统中使用Framebuffer驱动程序来控制LCD显示设备。Framebuffer是一块内存,保存着一帧图像的每一个像素颜色值。通过设置LCD控制器的时序、信号极性以及分配Framebuffer的大小和位置,可以实现在LCD上显示图像。在应用层,可以使用ioctl函数读取屏幕的参数信息,然后通过mmap映射Framebuffer,在Framebuffer中写入数据来实现图像的显示。Framebuffer应用的好处是可以直接对显存缓冲区进行读写操作,不必关心硬件的物理地址,简化了读写速度和方便性。\[2\]\[3\] #### 引用[.reference_title] - *1* [Framebuffer的配置及应用——先转载留着,以后一定要弄懂](https://blog.csdn.net/weixin_33890499/article/details/85844617)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [【嵌入式Linux】嵌入式Linux应用开发基础知识之Framebuffer应用编程和字符汉字显示](https://blog.csdn.net/weixin_43444989/article/details/122918794)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [19.Frambuffer应用编程](https://blog.csdn.net/qq_42174306/article/details/125589673)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值