嵌入式学习第三十六!(FrameBuffer的使用)

1. FrameBuffer的介绍:

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

    用户无法通过用户内存空间向显存内存空间写入RGB颜色值,但可以通过内存映射单元,将用户空间的部分内存,映射到显存空间,实现RGB颜色值数据的写入,再通过显卡的转换在显示屏中显示。即通过内存映射技术,向显存中写入RGB颜色值,从而实现像素点的绘制

2. FrameBuffer的使用:

    控制fb,对于应用层,通过操作/dev/fb*,通过ioctl来用各种命令控制fb,可在linux系统中的/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>中还提供了专门的结构体类型,用来存放上述两个参数,如下就是存放可变参数的结构体类型:

struct fb_var_screeninfo {
    __u32 xres;         /* visible resolution 可视画面的x、y轴分辨率      */ 
    __u32 yres;
    __u32 xres_virtual;     /* virtual resolution       */
    __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 */
}

3. FrameBuffer用到的函数接口:

    1. 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 *:返回映射欲映射内存的首地址

        举例:

unsigned int* addr = mmap(NULL, 800*480*4, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);

    2. munmap:

int munmap(void *addr, size_t length);

        功能:解除内存映射

        参数:

            addr:映射内存的地址

            length:映射内存大小

    3.ioctl:

int ioctl(int fd, int request, ...);

        功能:执行各种设备控制操作

        参数:

            fd:表示打开设备的文件描述符

            request:是一个整数,表示对设备执行的操作类型或请求,这个参数指定了要执行的特定控制命令

            ...:表示可选的参数,具体取决于 'request' 参数的含义

        举例:

ioctl(fd, FBIOGET_VSCREENINFO, &vinfo);	//获取屏幕信息(可变)

4. FrameBuffer的使用:

    1. 初始化FrameBuffer:

#define RGB888_FMT 32
#define RGB565_FMT 16

int fb = 0;
size_t size = 0;
void *pmem = NULL;
struct fb_var_screeninfo vsinf;

int Init_FrameBuffer(const char *fbname)
{
	fb = open(fbname, O_RDWR);
	if(fb == -1)
	{
		perror("fail to open fb");
		return -1;
	}
	
	int ret = ioctl(fb, FBIOGET_VSCREENINFO, &vsinf);
	if(ret < 0)
	{
		perror("fail to ioctl");
		return -1;
	}

	printf("xres: %d, yres: %d\n", vsinf.xres, vsinf.yres);
	printf("xres_virtual: %d, yres_virtual: %d\n", vsinf.xres_virtual, vsinf.yres_virtual);
	printf("bits_per_pixel: %d\n", vsinf.bits_per_pixel);
	
	size = vsinf.xres_virtual * vsinf.yres_virtual * vsinf.bits_per_pixel / 8;
	pmem = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fb, 0);
	if(pmem == (void *)-1)
	{
		perror("fail to mmap");
		return -1;
	}

	return 0;
}

    2. 绘制一个点:

void Draw_Point(int x, int y, unsigned int col)
{
	if(x > vsinf.xres_virtual || y > vsinf.yres_virtual)
	{
		return;
	}

	if(vsinf.bits_per_pixel == RGB888_FMT)
	{
		unsigned int *p = pmem;
		*(p + y * vsinf.xres_virtual + x) = col;
	}
	else if(vsinf.bits_per_pixel == RGB565_FMT)
	{
		unsigned short *p = pmem;
		*(p + y * vsinf.xres_virtual + x) = col;
	}

	return;
}

    3. 绘制一条横线:

void Draw_Transverse_Line(int x_begin, int x_end, int y, unsigned int col)
{
	if(y > vsinf.yres_virtual || x_begin > vsinf.xres_virtual || x_end > vsinf.xres_virtual)
	{
		return;
	}

	if(vsinf.bits_per_pixel == RGB888_FMT)
	{
		unsigned int *p = pmem;
		for(int i = x_begin; i <= x_end; i++)
		{
			*(p + y * vsinf.xres_virtual + i) = col;
		}

	}
	else if(vsinf.bits_per_pixel == RGB565_FMT)
	{
		unsigned short *p = pmem;
		for(int i = x_begin; i <= x_end; i++)
		{
			*(p + y * vsinf.xres_virtual + i) = col;
		}
	}
	
	return;
}

    4. 绘制一条竖线:

void Draw_Vertical_Line(int x, int y_begin, int y_end, unsigned int col)
{
	if(x > vsinf.xres_virtual || y_begin > vsinf.yres_virtual || y_end > vsinf.yres_virtual)
	{
		return;
	}

	if(vsinf.bits_per_pixel == RGB888_FMT)
	{
		unsigned int *p = pmem;
		for(int i = y_begin; i <= y_end; i++)
		{
			*(p + i * vsinf.xres_virtual + x) = col;
		}

	}
	else if(vsinf.bits_per_pixel == RGB565_FMT)
	{
		unsigned short *p = pmem;
		for(int i = y_begin; i <= y_end; i++)
		{
			*(p + i * vsinf.xres_virtual + x) = col;
		}
	}

	return;
}

    5. 绘制一个矩形:

void Draw_Rectangle(int x_begin, int y_begin, int x_end, int y_end, unsigned int col)
{
	if(x_begin > vsinf.xres_virtual || y_begin > vsinf.yres_virtual || x_end > vsinf.xres_virtual || y_end > vsinf.yres_virtual)
	{
		return;
	}

	Draw_Transverse_Line(x_begin, x_end, y_begin, col);
	Draw_Vertical_Line(x_begin, y_begin, y_end, col);
	Draw_Transverse_Line(x_begin, x_end, y_end, col);
	Draw_Vertical_Line(x_end, y_begin, y_end, col);

	return;
}

    6. 绘制一个圆:

void Draw_Circle(int x, int y, int R, unsigned int col)
{
	if(x > vsinf.xres_virtual || y > vsinf.yres_virtual || x + R > vsinf.xres_virtual || y + R > vsinf.yres_virtual)
	{
		return;
	}

	if(vsinf.bits_per_pixel == RGB888_FMT)
	{
		int x0, y0;
		for(float si = 0; si < 360; si += 0.1)
		{
			x0 = R * cos(2 * 3.1415926 / 360 * si) + x;
			y0 = R * sin(2 * 3.1415926 / 360 * si) + y;
			Draw_Point(x0, y0, col);
		}

	}
	else if(vsinf.bits_per_pixel == RGB565_FMT)
	{
		int x0, y0;
		for(float si = 0; si < 360; si += 0.1)
		{
			x0 = R * cos(2 * 3.1415926 / 360 * si) + x;
			y0 = R * sin(2 * 3.1415926 / 360 * si) + y;
			Draw_Point(x0, y0, col);
		}
	}	
}

    7. 显示一张bmp格式的图片:

void Draw_Bmp(const char *bmpname, int w, int h)
{
	int fp = open(bmpname, O_RDONLY);
	if(fp == -1)
	{
		perror("fail to open");
		return;
	}
	
	lseek(fp, 54, SEEK_SET);

	char *pbmp = malloc(w * h * 24 / 8);
	if(pbmp == NULL)
	{
		perror("fail to malloc");
		return;
	}

	read(fp, pbmp, w*h*24/8);
	char *p = pbmp;

	for(int j = h-1; j >= 0; j--)
	{
		for(int i = 0; i < w; i++)
		{
			unsigned char r, g, b;
			b = *p; p++;
			g = *p; p++;
			r = *p; p++;
			if(vsinf.bits_per_pixel == RGB888_FMT)
			{
				unsigned int col = r << 16 | g << 8 | b; 
				Draw_Point(i, j, col);
			}	
			else if(vsinf.bits_per_pixel == RGB565_FMT)
			{
				unsigned short col = (r >> 3) << 11 | (g >> 2) << 5 | b;
				Draw_Point(i, j, col);
			}

		}
	}

	free(pbmp);
	close(fp);

	return;
}

    8. 清屏:

void Clear_Screen(void)
{
	if(vsinf.bits_per_pixel == RGB888_FMT)
	{
		unsigned int *p = pmem;
		for(int j = 0; j <= vsinf.yres_virtual; j++)
		{
			for(int i = 0; i <= vsinf.xres_virtual; i++)
			{
				*(p + j * vsinf.xres_virtual + i) = 0x00000000;
			}
		}
	}
	else if(vsinf.bits_per_pixel == RGB565_FMT)
	{
		unsigned int *p = pmem;
		for(int j = 0; j <= vsinf.yres_virtual; j++)
		{
			for(int i = 0; i <= vsinf.xres_virtual; i++)
			{
				*(p + j * vsinf.xres_virtual + i) = 0x00000000;
			}
		}
	}

	return;
}

    9. 关闭FrameBuffer:

void UnInit_FrameBuffer(void)
{
	munmap(pmem, size);
	close(fb);

	return;
}

相关推荐

  1. 嵌入学习

    2024-05-15 13:22:17       52 阅读
  2. LVGL 8.x适配嵌入LinuxFramebuffer

    2024-05-15 13:22:17       68 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-05-15 13:22:17       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-05-15 13:22:17       100 阅读
  3. 在Django里面运行非项目文件

    2024-05-15 13:22:17       82 阅读
  4. Python语言-面向对象

    2024-05-15 13:22:17       91 阅读

热门阅读

  1. 30、Flink 的故障恢复详解

    2024-05-15 13:22:17       22 阅读
  2. 三数之和算法题(LeetCode)

    2024-05-15 13:22:17       29 阅读
  3. Spring Boot学习

    2024-05-15 13:22:17       30 阅读
  4. fastapi+vue实现导出功能

    2024-05-15 13:22:17       31 阅读
  5. 深入理解Qt的信号与槽机制

    2024-05-15 13:22:17       25 阅读