Linux FrameBuffer(一) —— FrameBuffer是什么?怎么用?

目录
一、FrameBuffer是什么
二、FrameBuffer怎么用
2.1 开发流程
2.2 FrameBuffer画图最简单代码


一、FrameBuffer是什么

简单理解
FrameBuffer就是一块显存,你往上面画什么,它就会显示什么。可以将它想象成一个二维平面,由一个个像素的组成,其分辨率宽度和高度的乘积就是整个FrameBuffer的像素点。例如:分辨率为800x600的FrameBuffer,就表示这块显存有600行,每行800个像素点。

补充:
FrameBuffer 也称帧缓存,是 Linux 内核将显存进行抽象后的一块缓存(内存),目的是为了给用户态进程提供一套直接写屏的接口,而不用关心物理显存的位置、换页机制等具体细节。一般在进行Linux系统的图形层开发时需要用到FrameBuffer的相关知识。

FrameBuffer设备文件一般为/dev/fb*,如果系统有多个FrameBuffer设备文件,则表示该系统可能有多个显卡,一个子设备号对应一个显卡。而一些嵌入式芯片平台将FrameBuffer设备与叠加图形层进行关联,下图是海思3531A平台的FrameBuffer设备文件,/dev/fb0表示图形层,/dev/fb3表示鼠标层。
在这里插入图片描述

像素格式和分辨率
即使Linux做了抽象,而不需要关系显存的其他细节,但是要往显示器显示图像或者画图,还是需要先设置好一些参数,例如像素格式分辨率。像素格式包含了一些像素点的信息,如"一个像素点占用多少字节的内存"、“颜色分量起始比特位”、"颜色分量所占比特长度"等等;分辨率则表示了总共有多少个像素点,有了像素格式和分辨率就可以知道这个帧缓存的总大小是多大。


二、FrameBuffer怎么用

2.1 开发流程

前面简单地介绍了FrameBuffer地一些基础知识,最主要的就是要知道 FrameBuffer 是一块缓存(内存),开发过程中就是进行一些简单设置后,可以对这块缓存(内存)直接读写并将写入的内容显示在屏幕上。一般 FrameBuffer 的开发过程如下:

FrameBuffer 开发流程
1.打开设备 #include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int framebuf_fd = open(fbPath, O_RDWR);
2.获取物理显存大小、跨度等固定信息 #include <sys/ioctl.h>
ioctl(framebuf_fd, FBIOGET_FSCREENINFO, &finfo)
3.获取并设置像素位深、像素格式、屏幕高宽等参数 #include <sys/ioctl.h>
ioctl(framebuf_fd, FBIOGET_VSCREENINFO, &vinfo)
ioctl(framebuf_fd, FBIOPUT_VSCREENINFO, &vinfo)
4.映射物理显存到用户虚拟内存空间 #include <sys/mman.h>
fbMapMem=(char*)mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, framebuf_fd, 0);
5.操作虚拟内存,完成具体绘制任务 fillRect(0xffff0000,0,0,30,30);
6.解除显存映射 #include <sys/mman.h>
munmap(fbMapMem, size);
7.关闭设备 #include <unistd.h>
close(framebuf_fd);

2.2 FrameBuffer画图最简单代码

跟据上面的开发流程,我写了下面这个在Linux的FrameBuffer上画图的.c文件,主要是更好地理解上面的开发流程,实际使用FrameBuffer应该会复杂一点,但流程差不多。可以直接把这个.c文件复制到Ubuntu或其他Linux平台编译,通过后运行,会看到左上角一直在画30*30大小的方块,效果如下:
在这里插入图片描述

// framebuffer.c
#include <stdio.h>
#include <linux/fb.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>

unsigned int fb_byteW=0, fb_byteH=0; // 用字节表示的宽度和高度
unsigned int bytesPerPixel = 0;	// 一个像素占用的字节数
char *fbMapMem = NULL;

void fillRect(int color, int x, int y, int w, int h)
{
	int i=0, j=0, offset = 0;
	if(bytesPerPixel==4)
	{
		for(i=0; i<h; i++)
		{
			offset = x*bytesPerPixel + (y+i)*fb_byteW;
			for(j=0; j<w; j++)
			{
				int *tmp = (int *)&fbMapMem[offset];
				*tmp = color;
				offset += bytesPerPixel;
			}
		}
	}
	else
		printf("error bytesPerPixel=%d\n", bytesPerPixel);
}

int main(int argc, char *argv[])
{
	// 1.打开设备
	char fbPath[64] = "/dev/fb0";
	int framebuf_fd = open(fbPath, O_RDWR);
	if ( framebuf_fd < 0 ) {
        printf("[%s:%d] open %s error \n", __FILE__,__LINE__,fbPath);
        return -1;
    }
	
	// 2.获取设备固定参数
	struct fb_fix_screeninfo finfo;
	if (ioctl(framebuf_fd, FBIOGET_FSCREENINFO, &finfo) < 0)
    {
        fprintf(stderr, "ioctl FBIOGET_FSCREENINFO err \r\n");
        return -1;
    }

	// 3.1 获取虚拟参数
	struct fb_var_screeninfo vinfo;
    if (ioctl(framebuf_fd, FBIOGET_VSCREENINFO, &vinfo) < 0)
    {
        fprintf(stderr, "ioctl FBIOGET_VSCREENINFO err \r\n");
        return -1;
    }

	// 3.2 设置虚拟参数
	bytesPerPixel = vinfo.bits_per_pixel / 8;
	vinfo.xres = vinfo.xres_virtual = finfo.line_length/bytesPerPixel;
	if (ioctl(framebuf_fd, FBIOPUT_VSCREENINFO, &vinfo) < 0)
    {
        fprintf(stderr, "ioctl FBIOPUT_VSCREENINFO err \r\n");
        return -1;
    }
	
	fb_byteW = vinfo.xres * bytesPerPixel;
	fb_byteH = vinfo.yres * bytesPerPixel;
	printf("[line:%d] line_length=%d res=[%dx%d], Bpp=%d ByteWH=[%d %d]\n",__LINE__,finfo.line_length,vinfo.xres,vinfo.yres,bytesPerPixel,fb_byteW, fb_byteH);
	
	// 4.映射物理显存到用户虚拟内存空间
	unsigned long size = vinfo.xres*vinfo.yres*bytesPerPixel;
    if (NULL == (fbMapMem=(char *)mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, framebuf_fd, 0)) )
    {
        fprintf(stderr, "mmap size %ld err \r\n", size);
        return -1;
    }
	
	// 5.操作虚拟内存,完成具体绘制任务,每隔一秒画一个颜色的正方形
	while(1)
	{
		fillRect(0xff0000,0,0,30,30);// 红色
		sleep(1);
		fillRect(0x00ff00,0,0,30,30);// 绿色
		sleep(1);
		fillRect(0x0000ff,0,0,30,30);// 蓝色
		sleep(1);
	}
	
	// 6.解除显存映射
	munmap(fbMapMem, size);
	
	// 7.关闭设备
	close(framebuf_fd);
	return 0;
}

要运行上面这个程序的话,一定要系统里有/dev/fb0的文件,如果你是比较旧的Ubuntu系统,且没有/dev/fb0文件的话,可以参考这篇文章:虚拟机的 Ubuntu 没有 /dev/fb0 的解决办法

其次,需要将Ubuntu切换道命令行模式,可以通过按快捷键 Ctrl + Alt + F1来切换到命令行模式,通过按Ctrl + Alt + F7切换到图形界面模式。切换到命令行模式也可以Ctrl + Alt + (F1~F6任意一个)去切换。


如果文章对你有用的话,点个赞让我知道 *_^
  • 13
    点赞
  • 68
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
Qt is a popular cross-platform framework for developing graphical user interfaces (GUI) and applications. It provides support for Linux framebuffer, which allows you to create GUI applications that can run directly on the Linux framebuffer without the need for an X server. To use Qt with Linux framebuffer, you can follow these general steps: 1. Install the required dependencies: Make sure you have the necessary libraries and development packages installed on your Linux system. This may include framebuffer-related libraries like `libdrm` and `libgbm`. 2. Configure Qt with framebuffer support: When building Qt from source, you can enable framebuffer support by passing the `-qt-libinput` flag to the `configure` script. For example: ``` ./configure -qt-libinput ``` 3. Build your Qt application: Once Qt is configured with framebuffer support, you can build your application using the `qmake` and `make` commands as usual. Make sure to set the appropriate target platform, such as `linuxfb`. 4. Run your Qt application on the Linux framebuffer: After building your application, you can run it directly on the Linux framebuffer by setting the appropriate environment variables. For example: ``` export QT_QPA_PLATFORM=linuxfb export QT_QPA_FB_TTY=/dev/fb0 ./your_application ``` By following these steps, you should be able to develop and run Qt applications using the Linux framebuffer as the target platform. Keep in mind that framebuffer support may vary depending on your specific Linux distribution and hardware setup.

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wkd_007

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值