我是靠谱客的博主 乐观白羊,最近开发中收集的这篇文章主要介绍framebuffer简介与应用framebuffer简介与应用,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

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
0x4606

我们主要使用FBIOGET_VSCREENINFOFBIOGET_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 */
  • 比较重要的可变参数有:
    • 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;
}
}
  • 上述代码先读取了fb的各种信息,然后根据读出来的信息画了一幅图像(两条线距离显示virtual边缘为50像素),如果该图像能被正确显示,则说明fb完全正常

最后

以上就是乐观白羊为你收集整理的framebuffer简介与应用framebuffer简介与应用的全部内容,希望文章能够帮你解决framebuffer简介与应用framebuffer简介与应用所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(46)

评论列表共有 0 条评论

立即
投稿
返回
顶部