Framebuffer应用编程

本文详细介绍了Linux系统中的Framebuffer设备驱动,包括读写/dev/fbX的操作,LCD应用编程,以及ioctl()函数的使用。通过ioctl()获取和设置Framebuffer设备的变量和固定参数信息,如分辨率、像素深度等。此外,还提供了测试代码示例,展示如何获取fb设备信息以及在fb设备上进行画点画线操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

 

1、Framebuffer设备驱动

2、读写/dev/fbX 测试

3、LCD应用编程

4、ioctl()操作

4.1、结构体

4.1.1、fb_var_screeninfo结构体

4.1.2、fb_fix_screeninfo结构体

5、测试代码

5.1、获取fb设备信息

5.2、fb设备画点画线


1、Framebuffer设备驱动

帧缓冲(framebuffer)是 Linux 系统中的一种显示驱动接口,它将显示设备(譬如 LCD) 进行抽象、 屏蔽了不同显示设备硬件的实现,对应用层抽象为一块显示内存(显存),它允许上层应用程序直接对显示缓冲区进行读写操作,而用户不必关心物理显存的位置等具体细节,这些都由Framebuffer设备驱动来完成。

注:FrameBuffer设备对应的设备文件为/dev/fbX。

2、读写/dev/fbX 测试

应用程序读写/dev/fbX 就相当于读写显示设备的显示缓冲区(显存),譬如 LCD 的分辨率是800*480,每一个像素点的颜色用 24 位(譬如 RGB888)来表示,那么这个显示缓冲区的大小就是 800 x 480 x 24 / 8 =1152000 个字节。 譬如执行下面这条命令将 LCD 清屏,也就是将其填充为黑色(假设 LCD 对应的设备节点是/dev/fb0,分辨率为 800*480, RGB888 格式):

dd if=/dev/zero of=/dev/fb0 bs=1024 count=1125

3、LCD应用编程

4、ioctl()操作

定义在<linux/fb.h>头文件中。

常用宏说明结构体
FBIOGET_VSCREENINFO获取FrameBuffer 设备的可变参数信息struct fb_var_screeninfo
FBIOGET_FSCREENINFO获取 FrameBuffer 设备的固定参数信息struct fb_fix_screeninfo
FBIOPUT_VSCREENINFO设置FrameBuffer 设备的可变参数信息struct fb_var_screeninfo
struct fb_var_screeninfo fb_var;
struct fb_fix_screeninfo fb_fix;
ioctl(fd, FBIOGET_VSCREENINFO, &fb_var);
ioctl(fd, FBIOGET_FSCREENINFO, &fb_fix);

4.1、结构体

定义在<linux/fb.h>头文件中。

4.1.1、fb_var_screeninfo结构体

struct fb_var_screeninfo {
	__u32 xres;			/* visible resolution		*/
	__u32 yres;
	__u32 xres_virtual;		/* virtual resolution		*/
	__u32 yres_virtual;
	__u32 xoffset;			/* offset from virtual to visible */
	__u32 yoffset;			/* resolution			*/

	__u32 bits_per_pixel;		/* guess what			*/
	__u32 grayscale;		/* 0 = color, 1 = grayscale,	*/
					/* >1 = FOURCC			*/
	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 */

	/* Timing: All values in pixclocks, except pixclock (of course) */
	__u32 pixclock;			/* pixel clock in ps (pico seconds) */
	__u32 left_margin;		/* time from sync to picture	*/
	__u32 right_margin;		/* time from picture to sync	*/
	__u32 upper_margin;		/* time from sync to picture	*/
	__u32 lower_margin;
	__u32 hsync_len;		/* length of horizontal sync	*/
	__u32 vsync_len;		/* length of vertical sync	*/
	__u32 sync;			/* see FB_SYNC_*		*/
	__u32 vmode;			/* see FB_VMODE_*		*/
	__u32 rotate;			/* angle we rotate counter clockwise */
	__u32 colorspace;		/* colorspace for FOURCC-based modes */
	__u32 reserved[4];		/* Reserved for future compatibility */
}
xres可视区域
yres
xres_virtual虚拟区域
yres_virtual
xoffset虚拟区域到可视区域之间的偏移
yoffset
bits_per_pixel像素深度 bpp。每个像素点使用多少个 bit 来描述
grayscale=0 表示彩色, =1 表示灰度, >1 表示 FOURCC 颜色
redRed 颜色分量色域偏移
greenGreen 颜色分量色域偏移
blueBlue 颜色分量色域偏移 
transp透明度分量色域偏移
nonstd

nonstd 等于 0,表示标准像素格式;不等于 0 则表示非标准像素格式

height用来描述 LCD 屏显示图像的高度(以毫米为单位)
width用来描述 LCD 屏显示图像的宽度(以毫米为单位)

注:通过 xres * yres * bits_per_pixel / 8 计算可得到整个显示缓存区的大小。

red、 green、 blue 描述了 RGB 颜色值中 R、 G、 B 三种颜色通道分别使用多少位以及它们各自的偏移量,通过 red、 green、 blue 变量可知道 LCD 的 RGB 像素格式(RGB888/RGB565)。

struct fb_bitfield {
	__u32 offset;			/* beginning of bitfield	*/
	__u32 length;			/* length of bitfield		*/
	__u32 msb_right;		/* != 0 : Most significant bit is */ 
					/* right */ 
};

4.1.2、fb_fix_screeninfo结构体

struct fb_fix_screeninfo {
	char id[16];			/* identification string eg "TT Builtin" */
	unsigned long smem_start;	/* Start of frame buffer mem */
					/* (physical address) */
	__u32 smem_len;			/* Length of frame buffer mem */
	__u32 type;			/* see FB_TYPE_*		*/
	__u32 type_aux;			/* Interleave for interleaved Planes */
	__u32 visual;			/* see FB_VISUAL_*		*/ 
	__u16 xpanstep;			/* zero if no hardware panning  */
	__u16 ypanstep;			/* zero if no hardware panning  */
	__u16 ywrapstep;		/* zero if no hardware ywrap    */
	__u32 line_length;		/* length of a line in bytes    */
	unsigned long mmio_start;	/* Start of Memory Mapped I/O   */
					/* (physical address) */
	__u32 mmio_len;			/* Length of Memory Mapped I/O  */
	__u32 accel;			/* Indicate to driver which	*/
					/*  specific chip/card we have	*/
	__u16 capabilities;		/* see FB_CAP_*			*/
	__u16 reserved[2];		/* Reserved for future compatibility */
};
id字符串形式的标识符
smem_start

显存的起始地址(物理地址)

注:在应用层无法直接使用

smem_len显存的长度
line_length一行的字节数

5、测试代码

5.1、获取fb设备信息

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

void fb_get_var_screeninfo(int fd)
{
	struct fb_var_screeninfo fb_var;
	ioctl(fd, FBIOGET_VSCREENINFO, &fb_var);
	printf("分辨率: %d*%d\n",fb_var.xres, fb_var.yres);
	printf("像素深度 bpp: %d\n",fb_var.bits_per_pixel);
	
	printf("虚拟分辨率: %d*%d\n",fb_var.xres_virtual, fb_var.yres_virtual);
	printf("虚拟分辨率->可视分辨率的偏移: x=%d,y=%d\n",fb_var.xoffset, fb_var.yoffset);
	
	printf("grayscale: %d\n",fb_var.grayscale);
	printf("nonstd: %d\n",fb_var.nonstd);
	printf("像素格式:A<%d %d %d> R<%d %d %d> G<%d %d %d> B<%d %d %d>\n",
		fb_var.transp.offset, fb_var.transp.length, fb_var.transp.msb_right,
		fb_var.red.offset, fb_var.red.length,fb_var.red.msb_right,
		fb_var.green.offset, fb_var.green.length,fb_var.green.msb_right,
		fb_var.blue.offset, fb_var.blue.length,fb_var.blue.msb_right);
	printf("height: %d\n",fb_var.height);	
	printf("width: %d\n",fb_var.width);	
}

void fb_get_fix_screeninfo(int fd)
{
	struct fb_fix_screeninfo fb_fix;
	ioctl(fd, FBIOGET_FSCREENINFO, &fb_fix);
	printf("id: %s\n",fb_fix.id);
	printf("line_length: %d\n",fb_fix.line_length);
}

int main(int argc, char *argv[])
{
	struct fb_fix_screeninfo fb_fix;
	struct fb_var_screeninfo fb_var;
	int fd;
	/* 打开 framebuffer 设备 */
	if (0 > (fd = open("/dev/fb0", O_WRONLY))) {
		perror("open error");
		exit(-1);
	}
	
	fb_get_var_screeninfo(fd);
	fb_get_fix_screeninfo(fd);
	close(fd);
	exit(0);
}

5.2、fb设备画点画线

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


static int width; //LCD X分辨率
static int height; //LCD Y分辨率
static unsigned int *screen_base = NULL; //映射后的显存基地址

/********************************************************************
 * 函数名称: lcd_draw_point
 * 功能描述: 打点
 * 输入参数: x, y, color
 * 返 回 值: 无
 ********************************************************************/
static void lcd_draw_point(unsigned int x, unsigned int y, unsigned int color)
{
    /* 对传入参数的校验 */
    if (x >= width)
        x = width - 1;
    if (y >= height)
        y = height - 1;

    /* 填充颜色 */
    screen_base[y * width + x] = color;
}

/********************************************************************
 * 函数名称: lcd_draw_line
 * 功能描述: 画线(水平或垂直线)
 * 输入参数: x, y, dir, length, color
 * 返 回 值: 无
 ********************************************************************/
static void lcd_draw_line(unsigned int x, unsigned int y, int dir,
            unsigned int length, unsigned int color)
{
    unsigned int end;
    unsigned long temp;

    /* 对传入参数的校验 */
    if (x >= width)
        x = width - 1;
    if (y >= height)
        y = height - 1;

    /* 填充颜色 */
    temp = y * width + x; //定位到起点
    if (dir) { //水平线
        end = x + length - 1;
        if (end >= width)
            end = width - 1;

        for ( ; x <= end; x++, temp++)
            screen_base[temp] = color;
    }
    else { //垂直线
        end = y + length - 1;
        if (end >= height)
            end = height - 1;

        for ( ; y <= end; y++, temp += width)
            screen_base[temp] = color;
    }
}

/********************************************************************
 * 函数名称: lcd_draw_rectangle
 * 功能描述: 画矩形
 * 输入参数: start_x, end_x, start_y, end_y, color
 * 返 回 值: 无
 ********************************************************************/
static void lcd_draw_rectangle(unsigned int start_x, unsigned int end_x,
            unsigned int start_y, unsigned int end_y,
            unsigned int color)
{
    int x_len = end_x - start_x + 1;
    int y_len = end_y - start_y - 1;

    lcd_draw_line(start_x, start_y, 1, x_len, color);//上边
    lcd_draw_line(start_x, end_y, 1, x_len, color); //下边
    lcd_draw_line(start_x, start_y + 1, 0, y_len, color);//左边
    lcd_draw_line(end_x, start_y + 1, 0, y_len, color);//右边
}

/********************************************************************
 * 函数名称: lcd_fill
 * 功能描述: 将一个矩形区域填充为参数color所指定的颜色
 * 输入参数: start_x, end_x, start_y, end_y, color
 * 返 回 值: 无
 ********************************************************************/
static void lcd_fill(unsigned int start_x, unsigned int end_x,
            unsigned int start_y, unsigned int end_y,
            unsigned int color)
{
    unsigned long temp;
    unsigned int x;

    /* 对传入参数的校验 */
    if (end_x >= width)
        end_x = width - 1;
    if (end_y >= height)
        end_y = height - 1;

    /* 填充颜色 */
    temp = start_y * width; 
    for ( ; start_y <= end_y; start_y++, temp+=width) {

        for (x = start_x; x <= end_x; x++)
            screen_base[temp + x] = color;
    }
}

int main(int argc, char *argv[])
{
    struct fb_fix_screeninfo fb_fix;
    struct fb_var_screeninfo fb_var;
    unsigned int screen_size;
    int fd;

    /* 打开framebuffer设备 */
    if (0 > (fd = open("/dev/fb0", O_RDWR))) {
        perror("open error");
        exit(EXIT_FAILURE);
    }

    /* 获取参数信息 */
    ioctl(fd, FBIOGET_VSCREENINFO, &fb_var);
    ioctl(fd, FBIOGET_FSCREENINFO, &fb_fix);

    screen_size = fb_fix.line_length * fb_var.yres;
    width = fb_var.xres;
    height = fb_var.yres;

    /* 将显示缓冲区映射到进程地址空间 */
    screen_base = mmap(NULL, screen_size, PROT_WRITE, MAP_SHARED, fd, 0);
    if (MAP_FAILED == (void *)screen_base) {
        perror("mmap error");
        close(fd);
        exit(EXIT_FAILURE);
    }

    /* 画正方形方块 */
    int w = height * 0.25; //方块的宽度为1/4屏幕高度
    lcd_fill(0, width-1, 0, height-1, 0x0); //清屏(屏幕显示黑色)
    lcd_fill(0, w, 0, w, 0xFF0000); //红色方块
    lcd_fill(width-w, width-1, 0, w, 0xFF00); //绿色方块
    lcd_fill(0, w, height-w, height-1, 0xFF); //蓝色方块
    lcd_fill(width-w, width-1, height-w, height-1, 0xFFFF00); //黄色方块

    /* 画白线 */
    lcd_draw_line(0, height * 0.5, 1, width, 0xFFFFFF);
    lcd_draw_line(width * 0.5, 0, 0, height, 0xFFFFFF);

    /* 画矩形 */
    unsigned int s_x, s_y, e_x, e_y;
    s_x = 0.25 * width;
    s_y = w;
    e_x = width - s_x;
    e_y = height - s_y;

    for ( ; (s_x <= e_x) && (s_y <= e_y);
            s_x+=5, s_y+=5, e_x-=5, e_y-=5)
        lcd_draw_rectangle(s_x, e_x, s_y, e_y, 0xFFFFFF);

    munmap(screen_base, screen_size); 
    close(fd);  
    exit(EXIT_SUCCESS); 
}
### 回答1: Framebuffer应用编程是一种在图形终端上编程的技术,在此基础之上可以进行多种应用,其中包括: 1、在LCD上显示图形: 通过Framebuffer应用编程技术,可以将图形数据写入Framebuffer中,然后由系统将Framebuffer上的数据显示到LCD屏幕上,从而实现在LCD屏幕上显示图形的功能。 2、显示一幅图像文件的图案: 同样通过Framebuffer应用编程技术,可以读取图像文件中的图像数据,将其写入Framebuffer中,然后由系统将Framebuffer上的数据显示到图形终端上,从而实现显示一幅图像文件的图案的功能。 需要注意的是,在进行Framebuffer应用编程时,需要详细了解分辨率、色深、像素布局等概念,以便在实现各种功能时能够精确控制图像的显示效果。此外,也需要根据具体的应用需求,选择适合的Framebuffer设备驱动程序和图像处理工具来完成各种操作。 ### 回答2: Framebuffer应用编程是指使用Linux Framebuffer驱动程序对图形系统进行编程开发,实现在LCD上显示图形或显示一幅图像文件的图案等功能。该技术可以方便地操作图像,包括绘图、图像处理、图像显示等等操作。 在LCD上显示图形需要先对LCD进行初始化,将待显示的图形或文本等信息储存在Framebuffer中,接着通过LCD的STN或TFT控制器将数据发送到屏幕上进行显示。在这个过程中需要考虑屏幕刷新率的问题,通常情况下一般在50~60Hz左右,否则会出现闪烁和撕裂现象,影响视觉效果。 显示一幅图像文件的图案需要读取图像文件,解析其中的图像数据,并将数据储存在Framebuffer中,接着执行刷新操作,将图像显示在LCD上。常见的图像格式有JPEG、PNG、BMP等,不同格式的处理方式也不同,需要根据实际要求进行适配。 Framebuffer应用编程Linux图形界面编程的基础,对于需要进行图形化开发的领域,如嵌入式系统、游戏开发、嵌入式医疗设备等等都有广泛应用。同时也需要开发者具备一定的图像处理、图形算法、嵌入式开发等技能储备。 ### 回答3: Framebuffer是一种广泛应用于图形处理和显示设备中的概念。在应用编程过程中,它可以用于实现很多不同的功能,其中包括在LCD上显示图形和显示图像文件的图案。 在LCD上显示图形 要在LCD上显示图形,首先需要将对应的图形数据写入Framebuffer中,然后通过设备驱动程序将Framebuffer中的数据映射到对应的LCD显示区域中。为了实现这一过程,需要开发对应的应用程序或者使用已有的图形库,并按照规定的格式对图形数据进行处理和传输。 通常情况下,图形数据需要经过转换和优化,以兼容不同的显示设备和分辨率。并且,为了保证显示效果的质量,还需要考虑灰度、色彩和对比度等方面的参数设置,进一步改善图形的可读性和丰富性。 显示一幅图像文件的图案 要显示一幅图像文件的图案,需要先进行图像文件的读取和解码,将解码后的数据写入Framebuffer中。此后,通过上述的驱动程序映射过程,可以将图像数据同步到对应的显示设备中,实现图像的显示。 对于不同的图像格式和压缩方式,需要采用不同的解码算法和参数设置,以保证解码质量和速度。同时,为了达到更好的显示效果和资源利用率,也需要进行必要的图像处理和优化,如缩放、抖动、锐化等处理。 总之,Framebuffer应用编程具有很高的灵活性和可扩展性,可以实现很多不同类型的图形和图像处理任务,可以满足不同用户的需要和要求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值