framebuffer简介与应用
2017-11-01 22:25
274 查看
framebuffer简介与应用
使用GUI测试framebuffer不太方便,最简单的方法是用应用层的小程序来测试
1.gpu与fb的关系
gpu就是soc中的一个外设,对外体现就是寄存器。cpu可以发命令给gpu,比如给两个端点,gpu就会去做具体的画线操作。这样就减轻了cpu的负担,有点类似于DMA的作用下图是一个典型的嵌入式系统显示机制
2.在系统中查看lcd参数
在测试前,最重要的就是把带有刷屏功能的应用程序关掉,否则我们无法观察到现象 输入
cat /sys/class/graphics/fb0/modes即可查看分辨率
输入
cat /dev/urandom > /dev/fb0即可知晓fb是否能正常工作
3.控制fb
对于应用层,通过操作/dev/fb*,通过ioctl来用各种命令控制fb那么怎么控制呢?命令又是什么呢?这些都在
<linux/fb.h>中提供。其实这个头文件是内核源码中的,由于交叉编译器中将其包含了,所以我们可以在应用层直接调用
进入内核源码中看看
<linux/fb.h>,里面定义了一些ioctl的命令
/* 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 0x46061
2
3
4
5
6
7
8
9
我们主要使用
FBIOGET_VSCREENINFO和
FBIOGET_FSCREENINFO命令。从字面意思我们不难看出,这两个命令的意思分别为
fb’s ioctl, to get variable screen info:获取应用程序可改变的参数(如设定的分辨率)
fb’s ioctl, to get fixed screen info:获取固定的参数(如屏幕的分辨率,一般只是拿来看看)
<linux/fb.h>中还提供了专门的结构体类型,用来存放上述两个参数,如下就是存放可变参数的结构体类型
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 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 */1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
比较重要的可变参数有:
xres、yres:可视画面的x、y轴分辨率(应用层改不了)
xres_virtual、yres_virtual:虚拟画面(即fb)x、y轴分辨率
xoffset、yoffset:可视画面相对于虚拟画面的x、y轴偏移量
bits_per_pixel:像素深度,详见LCD详解
虚拟画面一般会被默认设为(不一定的)可视画面的两倍,这种结构被称之为“双缓冲机制”,这样做的好处是可以一边显示,一边缓冲下一幅画面
4.建立显存映射
显示画面的输出,实际是通过往显存里面写像素数据来实现的。由于显存实际是处于内核态的物理内存,所以下一步要把这块物理内存映射到用户态,所谓“映射”就可以理解为建立了一个“符号链接”,这样应用程序就可以直接操作这块物理内存了建立映射主要是使用mmap这个api,mmap的原型可以用man手册查看,
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
值得注意的是第一个参数,第一个参数是自选地址,意思是应用程序可以选一个自己喜欢的地址值,然后mmap可以把显存映射到该地址。如果参数值为NULL的话,系统将为我们自动分配一个地址,返回值就是该地址。
其他参数没什么好注意的,看看man手册即可
5.输出画面数据
我们有了显存之后,就可以将画面数据写入显存了。可是怎么写,写什么呢?对于我们当前的环境, xres_virtual、yres_virtual分别为800,960;bpp(像素深度)为32位;所以每个像素用一个int来表示,虚拟屏幕尺寸为800*960像素。
显存中,数据排布的顺序就是按照虚拟屏幕中像素数据从上到下,从左到右的数据来排布。而每一个像素数据则按照A(透明度)、R(红)、G(绿)、B(蓝)的顺序排布的。说实话显存中数据的排布很简单,非常符合人类的思维
6.程序分析
#include <stdio.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/ioctl.h> #include <fcntl.h> #include <linux/fb.h> #include <sys/mman.h> #define FBDEVICE "/dev/fb0" void draw_back(unsigned int *pfb, unsigned int width, unsigned int height, unsigned int color); void draw_line(unsigned int *pfb, unsigned int width, unsigned int height); int main(void) { int fd = -1; int ret = -1; unsigned int *pfb = NULL; struct fb_fix_screeninfo finfo; struct fb_var_screeninfo vinfo; fd = open(FBDEVICE, O_RDWR); if (fd < 0) { perror("open"); return -1; } printf("open %s success \n", FBDEVICE); /*获取fb信息*/ ret = ioctl(fd, FBIOGET_FSCREENINFO, &finfo); if (ret < 0) { perror("ioctl"); return -1; } ret = ioctl(fd, FBIOGET_VSCREENINFO, &vinfo); if (ret < 0) { perror("ioctl"); return -1; } /*建立mmap映射*/ pfb = mmap(NULL, finfo.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (NULL == pfb) { perror("mmap"); return -1; } printf("pfb :0x%x \n", pfb); draw_back(pfb, vinfo.xres_virtual, vinfo.yres_virtual, 0xffff0000); draw_line(pfb, vinfo.xres_virtual, vinfo.yres_virtual); close(fd); return 0; } void draw_back(unsigned int *pfb, unsigned int width, unsigned int height, unsigned int color) { unsigned int x, y; for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { *(pfb + y * width + x) = color; } } } void draw_line(unsigned int *pfb, unsigned int width, unsigned int height) { unsigned int x, y; for (x = 50; x < width - 50; x++) { *(pfb + 50 * width + x) = 0xffffff00; } for (y = 50; y < height -50; y++) { *(pfb + y * width + 50) = 0xffffff00; } }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
上述代码先读取了fb的各种信息,然后根据读出来的信息画了一幅图像(两条线距离显示virtual边缘为50像素),如果该图像能被正确显示,则说明fb完全正常
相关文章推荐
- framebuffer简介与应用
- Xcode使用介绍之一:Xcode简介+创建App应用
- Tornado应用笔记01-简介
- 最新的Javascript和CSS应用技巧荟萃[简介]
- java实战(八)--------Java框架——SSH框架应用简介
- [Django]第二篇:MVC框架简介以及Django简单应用
- 在Silverlight+WCF中应用以角色为基础的安全模式(一)基础篇之角色为基础的安全模式简介
- FrameBuffer 原理、实现与应用
- 国内云存储产品应用简介
- 3D触控简介:建立数字刻度应用及快速活动栏
- Maven 应用简介
- 移动应用实战(移动OA)之二_jQuery Mobile简介
- Servlet简介 以及servlet一些细节 servletconfig servletcontext 的几个应用
- 手机网络应用客户端软件开发实践简介
- FileSystemObject简介及应用
- 实战CGLIB系列文章之开篇:CGLIB简介、原理与应用
- 老李推荐:第2章1节《MonkeyRunner源码剖析》了解你的测试对象: NotePad应用简介
- 基于ACIS/HOOPS的3D应用开发简介
- 【SSH】Spring简介和应用
- 基于ACIS/HOOPS的3D应用开发简介