基于x86_64 ubuntu22.04的framebuffer编程

news2024/11/25 19:51:11

文章目录

  • 前言
  • 一、framebuffer简介
  • 二、framebuffer接口
    • 1.framebuffer设备描述信息
    • 2.framebuffer访问接口
    • 3.查询/设置可更改信息
  • 三、使用步骤


前言

前段时间由于笔记本没有保管好,LCD显示屏压碎了。于是,将笔记本电脑拆开查看LCD型号。在淘宝上下单买了块新的,给老伙计重新装上了。又给笔记本重新装了系统,这个过程甚是艰辛。本来是想装WIN10 X64系统的,制作好U盘启动后程序卡在了win10的启动界面。本来以为可能是内存不够,在网上下单又购买了4G内存条给笔记本换上。装好内存条后,笔记本的运行速度确实有所提升。但是,安装win10 仍然是同样的情况。看来是CPU的性能不够,打算升级CPU。在网上查阅了很多关于升级CPU的帖子,最终结论是主板南桥芯片H55限制了CPU只能选择一代CPU。一代CPU都是双核四线程的,对性能提升应该不是很大。基于此,重新安装回win 7 x64旗舰版。装软件的时候发现,win7 跟 XP一样很多软件都不适用了。而且,还有大量的补丁。最终,选择了给它装上ubuntu 22.04。于是有了本文的硬件基础,本文就是在这台x86_64 ubuntu22.04上做的实验。

一、framebuffer简介

framebuffer是对LCD显示屏的硬件抽象,通过对framebuffer的操作可以直接显示到LCD上。framebuffer是一个字符设备,它向上为用户层提供统一的访问接口,向下屏蔽底层各类硬件显示设备的差异,提高framebuffer设备应用程序的兼容性和可移植性。
framebuffer是一个标准的字符设备,主设备号为29。linux系统最大支持32个framebuffer设备,次设备号一般从0开始,依次为0到31。与其它设备一样,设备节点位于/dev目录下面,一般命名为fbx。例如,/dev/fb0。

二、framebuffer接口

对于framebuffer应用程序开发,不需关心底层的具体实现,只需知道具体访问接口、数据结构以及显示设备的一些必要信息,即可开发应用程序。

1.framebuffer设备描述信息

framebuffer设备信息包括两部分,分别是不可更改和可更改信息。设备信息描述数据结构位于“include/uaip/linux/fb.h”中声明。
不可更改信息描述的是显示设备的固有属性、物理内存地址、物理内存大小等等;对于应用层来说,该部分信息可以用来查询显示设备固有属性信息,对于具体应用过程关联性不大。
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 */
};

第二部分可更改的信息,涉及显示设备物理分辨率、虚拟分辨率、像素位宽,这部分信息在应用编程需要关注的,以计算显示位置、颜色、映射内存等等。该部分也设计显示设备的固有信息,但应用程序可以通过接口修改。

						struct fb_var_screeninfo{
							__u32 xres;			/* 可视分辨率(物理分辨率) */
							__u32 yres;
						    
							__u32 xres_virtual;	/* 虚拟分辨率 */
							__u32 yres_virtual;
							__u32 xoffset;		/* 虚拟分辨率相对可视分配率偏移值 */
							__u32 yoffset;			
						
							__u32 bits_per_pixel;	/* 像素位宽,每个像素用多少未表示 */
							__u32 grayscale;		/* 灰度等级,0表示彩色,1表示灰度(黑白屏)*/
							
						    /* 缓存RGB位域 */
							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 */
						
							/* 实际显示屏(LCD)参数,根据LCD手册设置,用户层一般不用更改 */
							__u32 pixclock;			/* 像素时钟 */
							__u32 left_margin;		/* 显示设备水平方向前肩,单位:时钟 */
							__u32 right_margin;		/* 显示设备水平方向后肩,单位:时钟 */
							__u32 upper_margin;		/* 显示设备垂直方式前肩,单位:行 */
							__u32 lower_margin;		/* 显示设备垂直方向后肩,单位:行 */
							__u32 hsync_len;		/* 显示设备水平方向有效区域,单位:时钟 */
							__u32 vsync_len;		/* 显示设备垂直方向有效区域,单位:行 */
						    
							__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 */
						}

framebuffer应用程序开发,主要关注的的成员参数是物理分辨率、像素位宽。物理分辨率和像素位宽决定了映射内存的大小,如一个LCD分辨率为1024768、像素位宽为32位;则需要的内存空间大小为:1024768*32/8=3145728字节。

2.framebuffer访问接口

framebuffer设备是一个标准的linux字符设备,可以通过标准虚拟文件接口open/read/write/ioctl/close访问。设备访问分为两部分数据,分别是控制数据流和显示数据流传。对控制数据流通过ioctl结合指定命令实现;对于显示流数据,由于数据量比较大,结合mmap函数,将framebuffer物理内存映射到用户态,直接访问物理内存。
ioctl(fd, cmd, param); /* 文件描述符, 命令字, 参数信息 */

	framebuffer设备ioctl命令位于“include/uapi/linux/fb.h”定义。
	/* include/uaip/linux/fb.h */
	/* ioctls
	   0x46 is 'F'			*/
	#define FBIOGET_VSCREENINFO	0x4600	/* 查询显示设备可更改信息 */
	#define FBIOPUT_VSCREENINFO	0x4601	/* 设置显示设备可更改信息 */
	#define FBIOGET_FSCREENINFO	0x4602	/* 查询显示设备不可更改信息 */
	#define FBIOGETCMAP			0x4604
	#define FBIOPUTCMAP			0x4605
	#define FBIOPAN_DISPLAY		0x4606
	......

3.查询/设置可更改信息

函数原型:
int ioctl(int fd, int cmd, struct fb_var_screeninfo *var);

cmd,命令字:FBIOGET_VSCREENINFO
var,设备可更改信息数据结构
返回,成功返回0,失败返回-1,错误码存于errno中

获取显示设备可更改信息伪代码:

int fb = 0;
struct fb_var_screeninfo var;

fb = open(“/dev/fb0”, O_RDWR);
if (fb < 0)
{
printf(“open fb device failed:%s\n”,strerror(errno));
return -1;
}
if (ioctl(fb, FBIOGET_VSCREENINFO, &var))
{
printf(“read fb device param failed:%s\n”,strerror(errno));
return -1;
}

查询不可更改信息
函数原型:
int ioctl(int fd, int cmd, struct fb_fix_screeninfo *var);

cmd,命令字:FBIOGET_FSCREENINFO
var,设备不可更改信息数据结构
返回,成功返回0,失败返回-1,错误码存于errno中

获取显示设备不可更改信息伪代码:
int fb = 0;
struct fb_fix_screeninfo fix;

fb = open(“/dev/fb0”, O_RDWR);
if (fb < 0)
{
printf(“open fb device failed:%s\n”,strerror(errno));
return -1;
}
if (ioctl(fb, FBIOGET_FSCREENINFO, &fix))
{
printf(“read fb device param failed:%s\n”,strerror(errno));
return -1;
}

三、使用步骤

应用程序访问一个framebuffer设备的的总体流程如下图。
在这里插入图片描述
实例:
获取framebuffer设备信息
“红—绿—蓝” 1秒周期循环刷新输出

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

struct _fb_info
{
int fd; /* framebuffer 文件描述符 /
uint8_t pbuf; / 映射内存 /
struct fb_fix_screeninfo fix;
struct fb_var_screeninfo var;/
framebuffer设备信息
/
};

struct _fb_info fb_app = {0};

/* 画点函数 */
static void draw_pixel(struct _fb_info *fb, int x, int y, uint32_t color)
{
uint8_t *poffset_buf = NULL;

poffset_buf = fb->pbuf + (x*fb->var.bits_per_pixel/8) 
			  + (y*fb->var.xres*fb->var.bits_per_pixel/8);	/* 计算内存偏移地址 */
*(uint32_t*)poffset_buf = color;	/* ARGB32格式 */

}

/* 全屏画点函数 */
static void fill_pixel(struct _fb_info *fb, uint32_t color)
{
int i, j;

for (i=0; i<fb->var.xres; i ++) 
{
    for (j=0; j<fb->var.yres; j ++) 
	{
		draw_pixel(fb, i, j, color);
    }
}

}

int main(int argc, char *argv[])
{
int ret = 0;
int mem_size = 0;

if (argc < 2)
{
	printf("parameter invalid\n");
	return -1;
}

fb_app.fd = open(argv[1], O_RDWR);
if (fb_app.fd < 0)
{
	printf("open device [%s] failed:%s\n", argv[1], strerror(errno));
	return -1;
}
printf("framebuffer device:%s\n", argv[1]);

/* 读取不可更改信息 */
ret = ioctl(fb_app.fd, FBIOGET_FSCREENINFO, &fb_app.fix);    
if (ret < 0)
{
	printf("read fb device fscreeninfo failed:%s\n", strerror(errno));
	close(fb_app.fd);
	return -1;
}
printf("device id:%s\n", fb_app.fix.id);
printf("smem_start:0x%x, smem_len:%u\n", fb_app.fix.smem_start, fb_app.fix.smem_len);    

/* 读取可更改信息 */
ret = ioctl(fb_app.fd, FBIOGET_VSCREENINFO, &fb_app.var);
if (ret < 0)
{
	printf("read fb device vscreeninfo failed:%s\n", strerror(errno));
	close(fb_app.fd);
	return -1;
}
printf("visible resolution:%d*%d\n", fb_app.var.xres, fb_app.var.yres);
printf("virtual resolution:%d*%d\n", fb_app.var.xres_virtual, fb_app.var.yres_virtual);
printf("pixel bits wide:%d\n", fb_app.var.bits_per_pixel);
printf("grayscale:%d\n", fb_app.var.grayscale);

mem_size = fb_app.var.xres * fb_app.var.yres * fb_app.var.bits_per_pixel / 8;	/* 计算内存 */
fb_app.pbuf = (uint8_t *)mmap(NULL, mem_size, PROT_READ|PROT_WRITE, MAP_SHARED, fb_app.fd, 0);
if (fb_app.pbuf == NULL)
{
	printf("fb device mmap failed:%s\n", strerror(errno));
	close(fb_app.fd);
	return -1;
}
memset(fb_app.pbuf, 0, mem_size);	/* 清屏操作(黑屏)*/
for (;;)
{
	fill_pixel(&fb_app, 0xffff0000);/* 红 */
	sleep(1);
	fill_pixel(&fb_app, 0xff00ff00);/* 绿 */
	sleep(1);
	fill_pixel(&fb_app, 0xff0000ff);/* 蓝 */
	sleep(1);
}
munmap(fb_app.pbuf, mem_size);
close(fb_app.fd);

return 0;	

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/969946.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Java 基础篇】玩转 Java String:技巧与实践

在Java编程中&#xff0c;字符串&#xff08;String&#xff09;是一个非常常见的数据类型&#xff0c;用于存储文本信息。无论是处理用户输入、读取文件内容还是与外部系统进行通信&#xff0c;字符串都扮演着重要的角色。本篇博客将深入讨论Java中的字符串&#xff08;String…

双边滤波 Bilateral Filtering

本文是对图像去噪领域经典的双边滤波法的一个简要介绍与总结&#xff0c;论文链接如下&#xff1a; https://users.soe.ucsc.edu/~manduchi/Papers/ICCV98.pdf 1.前言引入 对一副原始灰度图像&#xff0c;我们将它建模为一张二维矩阵u&#xff0c;每个元素称为一个像素pixel&am…

PID串行多闭环控制与并行多闭环控制的优缺点分析和应用比较

导言&#xff1a; 在自动控制领域&#xff0c;PID控制器是一种经典的控制策略&#xff0c;被广泛应用于各种工业和非工业过程。随着控制系统的复杂性增加&#xff0c;PID串行多闭环控制和PID并行多闭环控制成为解决复杂控制问题的重要方法。本文将从优点和缺点的角度对这两种控…

大数据Flink(七十二):SQL窗口的概述和Over Windows

文章目录 SQL窗口的概述和Over Windows 一、窗口的概述

【100天精通Python】Day53:Python 数据分析_NumPy数据操作和分析进阶

目录 1. 广播 2 文件输入和输出 3 随机数生成 4 线性代数操作 5 进阶操作 6 数据分析示例 1. 广播 广播是NumPy中的一种机制&#xff0c;用于在不同形状的数组之间执行元素级操作&#xff0c;使它们具有兼容的形状。广播允许你在不显式复制数据的情况下&#xff0c;对不同…

2022年09月 C/C++(七级)真题解析#中国电子学会#全国青少年软件编程等级考试

C/C编程&#xff08;1~8级&#xff09;全部真题・点这里 第1题&#xff1a;二叉树的深度 给定一棵二叉树&#xff0c;求该二叉树的深度 二叉树深度定义&#xff1a;从根结点到叶结点依次经过的结点&#xff08;含根、叶结点&#xff09;形成树的一条路径&#xff0c;最长路径的…

读SQL学习指南(第3版)笔记10_元数据与大数据

1. 元数据 1.1. metadata 1.2. 关于数据的数据 1.3. 数据字典 1.3.1. ⒅与外键关联的数据表/列 1.3.2. ⒄外键列 1.3.3. ⒃外键名 1.3.4. ⒂存储索引的信息 1.3.5. ⒁索引列的排序&#xff08;升序或降序&#xff09; 1.3.6. ⒀已索引的列 1.3.7. ⑿索引类型&#xf…

CSDN的好处

社区交流&#xff1a;CSDN是一个广大的程序员社区&#xff0c;有很多技术大牛和优秀开发者&#xff0c;可以在这里进行技术交流和讨论&#xff0c;获取最新的技术动态和资源。 学习资源&#xff1a;CSDN上有很多高质量的技术文章、教程和视频资源&#xff0c;可以帮助程序员不…

2023-9-3 筛质数

题目链接&#xff1a;筛质数 埃氏筛法 #include <iostream>using namespace std;const int N 1000010;int cnt; bool st[N];bool get_primes(int n) {for(int i 2; i < n; i ){if(!st[i]){cnt ;for(int j i i; j < n; j i) st[j] true;}} }int main() {int …

linux深入理解多进程间通信

1.进程间通信 1.1 进程间通信目的 数据传输&#xff1a;一个进程需要将它的数据发送给另一个进程资源共享&#xff1a;多个进程之间共享同样的资源。通知事件&#xff1a;一个进程需要向另一个或一组进程发送消息&#xff0c;通知它&#xff08;它们&#xff09;发生了某种事件…

AUTOSAR规范与ECU软件开发(实践篇)7.11 MCAL配置验证与代码生成

在配置完所需MCAL模块之后&#xff0c; 就可以进行配置验证与代码生成。MCAL配置工具的工具栏如图7.64所示。 其中&#xff0c; 右起第二个按钮为“Verify selected project”&#xff0c; 点击之后将进行配置验证。 右起第一个按钮为“Generate Code for the currently select…

小小一个设置程序高级感拉满

手动设置 结果如下 代码设置&#xff1a; procedure TForm1.Button1Click(Sender: TObject); begin TStyleManager.TrySetStyle(cbxVclStyles.Text); end;procedure TForm1.FormCreate(Sender: TObject); var StyleName:string; begin for StyleName in TStyleManager.StyleNa…

查询优化器内核剖析之从一个实例看执行计划

学习查询优化器不是我们的目的&#xff0c;而是通过 它&#xff0c;我们掌握 SQL Server 是如何处理我们的 SQL 的&#xff0c;掌握执行计划&#xff0c;掌握为什么产生 I/O 问题&#xff0c; 为什么 CPU 使用老高&#xff0c;为什么你的索引加了不起作用... 如果&#xff0c;…

数学建模--整数规划匈牙利算法的Python实现

目录 1.算法流程简介 2.算法核心代码 3.算法效果展示 1.算法流程简介 #整数规划模型--匈牙利算法求解 """ 整数规划模型及概念&#xff1a;规划问题的数学模型一般由三个因素构成 决策变量 目标函数 约束条件&#xff1b;线性规划即以线性函数为目标函数&a…

Python开源项目月排行 2023年8月

#2023年8月2023年9月2日1facechain一款可以用于打造个人数字形象的深度学习模型工具。用户只需提供最低三张照片即可获得独属于自己的个人形象数字替身。FaceChain 支持在梯度的界面中使用模型训练和推理能力&#xff0c;也支持资深开发者使用 python 脚本进行训练推理。2Qwen-…

CXL寄存器介绍(3)- CXL MMIO

&#x1f525;点击查看精选 CXL 系列文章&#x1f525; &#x1f525;点击进入【芯片设计验证】社区&#xff0c;查看更多精彩内容&#x1f525; &#x1f4e2; 声明&#xff1a; &#x1f96d; 作者主页&#xff1a;【MangoPapa的CSDN主页】。⚠️ 本文首发于CSDN&#xff0c…

【SpringSecurity】六、基于数据库的认证与授权

文章目录 1、数据库表设计2、测试代码准备3、新建安全用户类4、实现UserDetailsService接口5、授权 1、数据库表设计 接下来基于数据库里的用户信息进行登录认证&#xff0c;以RBAC设计表&#xff0c;分别为&#xff1a; 用户表sys_user &#xff1a;除了基本信息外&#xff…

pytorch(b站小土堆学习笔记P1-P15)

P3. Python学习中的两大法宝函数&#xff08;当然也可以用在PyTorch&#xff09; import torch#查看pytorch有哪些指令 print(dir(torch)) print(dir(torch.cuda)) #查看每条指令怎么用 help(torch.cuda.is_available) P4. PyCharm及Jupyter使用及对比 P5 dataset和dataloade…

肖sir__设计测试用例方法之场景法04_(黑盒测试)

设计测试用例方法之场景法 1、场景法主要是针对测试场景类型的&#xff0c;顾也称场景流程分析法。 2、流程分析是将软件系统的某个流程看成路径&#xff0c;用路径分析的方法来设计测试用例。根据流程的顺序依次进行组合&#xff0c;使得流程的各个分支能走到。 举例说明&…

Pinely Round 2 (Div. 1 + Div. 2) F. Divide, XOR, and Conquer(区间dp)

题目 给定长为n(n<1e4)的数组&#xff0c;第i个数为ai(0<ai<2的60次方) 初始时&#xff0c;区间为[1,n]&#xff0c;也即l1&#xff0c;rn&#xff0c; 你可以在[l,r)中指定一个k&#xff0c;将区间分成左半边[l,k]、右半边[k1,r] 1. 如果左半边异或和与异或和的异…