2

嵌入式Linux—Framebuffer应用编程 - Tayoou

 1 year ago
source link: https://www.cnblogs.com/Tayoou/p/17114400.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

嵌入式Linux—Framebuffer应用编程

Framebuffer 应用编程

Frame的意思是帧,buffer的意思是缓冲区。Framebuffer就是一块内存(硬件设备),里面保存着一帧图像。

ioctl()函数解析

ioctl()函数非常强大。不同的驱动程序内部会实现不同的 ioctl() ,可以使用各种 ioctl() 跟驱动程序交互:可以传数据给驱动程序,也可以从驱
动程序中读出数据。

#include <sys/ioctl.h>

函数原型:

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

函数说明:
① fd 表示文件描述符;
② request 表示与驱动程序交互的命令, 用不同的命令控制驱动程序输出我们需要的数据
③ … 表示可变参数 arg, 根据 request 命令,设备驱动程序返回输出的数据。
④ 返回值: 打开成功返回0,失败将返回-1

1.获取framebuffer描述符

fd_fb = open("/dev/fb0", O_RDWR);  //可读可写
	if(fd_fb == -1) {
		printf("can not open /dev/fb0\n");
		return -1;
	}

2.获取屏幕可变参数

if(ioctl(fd_fb, FBIOGET_VSCREENINFO, &var)) { //结构体名不是地址,需要取地址。FBIOGET_VSCREENINFO是获取可变参数(fb.h)
		printf("can not get var\n");
		return -1;
	} 

3.计算framebuffer空间大小

line_width = var.xres * var.bits_per_pixel / 8;
	pixel_width = var.bits_per_pixel / 8;
	screen_size = var.xres * var.yres * var.bits_per_pixel / 8;  //单位:字节
	fb_base = (unsigned char*)mmap(NULL, screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);
	if(fb_base == (unsigned char*)-1) {
		printf("can not mmap\n");
		return -1;
	}

4.不同的RGB格式转换

switch(var.bits_per_pixel) 
	{
		case 8:
			{
				/*代码*/
				break;
			}
		case 16:
			{
				/* 32位转换为RGB565 */
				red = (color >> 16) & 0xff;   //保留17-24位
				green = (color >> 8) & 0xff;  //保留8-16位
				blue = (color >> 0) & 0xff;   //保留0-8位
				color = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3);  //组合为16bit
				*add_16 = color;   //像素点对应的地址空间赋值
				break;
			}
		case 32:
			{
				*add_32 = color;
				break;
			}
		default:
			printf("can't surport %dbpp\n", var.bits_per_pixel);
			break;
	}

完整程序如下:

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

int fd_fb;    //文件描述符
int screen_size;  //屏幕总字节数(framebuffer的大小)
struct fb_var_screeninfo var;
unsigned char *fb_base;
unsigned int line_width;   //行字节
unsigned int pixel_width;  //像素字节

void lcd_put_pixel(int x, int y, unsigned int color) {
	unsigned char *add_8 = fb_base + y*line_width + x*pixel_width; //像素点对应的内存地址
	unsigned short *add_16;
	unsigned int *add_32;

	unsigned int red, green, blue;

	add_16 = (unsigned short*)add_8;  //8位转换为16位
	add_32 = (unsigned int*) add_8;

	switch(var.bits_per_pixel) 
	{
		case 8:
			{
				/*代码*/
				break;
			}
		case 16:
			{
				/* 32位转换为RGB565 */
				red = (color >> 16) & 0xff;   //保留17-24位
				green = (color >> 8) & 0xff;  //保留8-16位
				blue = (color >> 0) & 0xff;   //保留0-8位
				color = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3);  //组合为16bit
				*add_16 = color;   //像素点对应的地址空间赋值
				break;
			}
		case 32:
			{
				*add_32 = color;
				break;
			}
		default:
			printf("can't surport %dbpp\n", var.bits_per_pixel);
			break;
	}

}

int main(int argc, char **argv)
{
	int i;

	/* 1.获取framebuffer描述符 */
	fd_fb = open("/dev/fb0", O_RDWR);  //可读可写
	if(fd_fb == -1) {
		printf("can not open /dev/fb0\n");
		return -1;
	}

	/* 2.获取屏幕可变参数 */
	if(ioctl(fd_fb, FBIOGET_VSCREENINFO, &var)) { //结构体名不是地址,需要取地址
		printf("can not get var\n");
		return -1;
	} 

	/* 3.计算framebuffer空间大小 **/
	line_width = var.xres * var.bits_per_pixel / 8;
	pixel_width = var.bits_per_pixel / 8;
	screen_size = var.xres * var.yres * var.bits_per_pixel / 8;  //单位:字节
	fb_base = (unsigned char*)mmap(NULL, screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);
	if(fb_base == (unsigned char*)-1) {
		printf("can not mmap\n");
		return -1;
	}

	/* 清屏: 全部设为白色 */
	memset(fb_base, 0xff, screen_size);

	/* 随便设置出100个为蓝色 */
	for (i = 0; i < 100; i++)
		lcd_put_pixel(var.xres/2+i, var.yres/2, 0x0000FF);
	
	munmap(fb_base , screen_size);
	close(fd_fb);

	return 0;
}

本文作者:Tayoou

本文链接:https://www.cnblogs.com/Tayoou/p/17114400.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK