一、framebuffer使用基础:

1. Linux是工作在保护模式下,所以用户态进程是无法象DOS那样使用显卡BIOS里提供的中断调用来实现直接写屏, Linux抽象出FrameBuffer这个设备来供用户态进程实现直接写屏。对于用户而言,framebuffer和/dev下面的其他设备没有 什么区别,用户可以把framebuffer 看成一块内存,既可以向这块内存中写入数据,也可以从这块内存中读取数据。在应 用程序中,一般通过将 FrameBuffer 设备映射到进程地址空间的方式使用。

2.在这种机制下,尽管Framebuffer需要真正的显卡驱动的支持,但所有显示任务都有CPU完成,因此CPU负担很重.

3.PCI 设备可以将自己的控制寄存器映射到物理内存空间,而后,对这些控制寄存器的访问,给变成了对物理内存的 访问。因此,这些寄存器又被称为"memio"。一旦被映射到物理内存,Linux 的普通进程就可以通过 mmap 将这些内存 I/O 映射到进程地址空间,这样就可以直接访问这些寄存器了。

4.帧缓冲设备属于字符设备,采用了“文件层-驱动层”的接口方式。Linux为帧缓冲设备定义的驱动层接口为struct fb_info结构。在文件层次上,用户调用struct file_operations的函数操作,其中间接调用struct fb_ops的函数来操作硬件.当向 内核注册FB设备的时候,也注册了struct fb_ops的指针.当打开fb设备时,先调用fb_drivers[]的xxxfb_init()来初始化设备;

5.第一个被注册的framebuffer的minor等于0,第二个被注册的framebuffer的minor等于1,以此类推。 如/dev/fb0,/dev/fb1。

可以用命令: #dd if=/dev/zero of=/dev/fb 清空屏幕.

如果显示模式是 1024x768-8 位色,用命令:$ dd if=/dev/zero of=/dev/fb0 bs=1024 count=768

清空屏幕 用命令: #dd if=/dev/fb of=fbfile 可以将fb中的内容保存下来; 
可以重新写回屏幕: #dd if=fbfile of=/dev/fb

二、framebuffer内部结构: 
Framebuffer对应的源文件在linux/drivers/video/目录下。总的抽象设备文件为fbcon.c,在这个目录下还有与各种显卡驱动相关的源文件。FrameBuffer设备驱动基于如下文件: 
1) linux/include/linux/fb.h定义一些变量结构和宏。
2) linux/drivers/video/fbmem.c实现设备入口和初始化。 
3) xxxfb.c: 自己添加的设备驱动文件,如struct fb_info;实现入口点函数: xxxfb_init; xxxfb_setup;
1.首先是fb.h。framebuffer设备很大程度上依靠了下面数据结构。 
1).Struct fb_var_screeninfo描述图形卡的特性的。通常是被用户设置的。 
2).Struct fb_fix_screeninfo定义了图形卡的硬件特性,是不能改变的。 
3).Struct fb_cmap描述设备无关的颜色映射信息。可以通过FBIOGETCMAP和FBIOPUTCMAP 对应的ioctl操作设定或获取颜色映射信息. 
4).Struct fb_info定义了当前图形卡framebuffer设备状态,一个图形卡可能有两个framebuffer,在这种情况下,就需要两个fb_info结构。这个结构是唯一在内核空间可见的。在这个结构中有一个fb_ops指针,指向驱动设备工作所需的函数集。 5).struct fb_ops用户应用可以使用ioctl()系统调用来操作设备,这个结构就是用以支持ioctl()的这些操作的。(注: fb_ops结构与file_operations 结构不同,fb_ops是底层操作的抽象,而file_operations是提供给上层系统调用的接口,可以直接调用.)ioctl()系统调用在文件fbmem.c中实现,通过观察可以发现ioctl()命令与fb_ops’s 中函数的关系:
FBIOGET_VSCREENINFO fb_get_var
FBIOPUT_VSCREENINFO fb_set_var
FBIOGET_FSCREENINFO fb_get_fix
FBIOPUTCMAP fb_set_cmap
FBIOGETCMAP fb_get_cmap
FBIOPAN_DISPLAY fb_pan_display 
如果我们定义了fb_XXX_XXX 方法,用户程序就可以使用FBIOXXXX宏的ioctl()操作来操作硬件。 
2.其次是fbmem.c。fbmem.c 处于Framebuffer设备驱动技术的中心位置.它为上层应用程序提供系统调用也为下一层的特定硬件驱动提供接口;那些底层硬件驱动需要用到这儿的接口来向系统内核注册它们自己. fbmem.c 为所有支持FrameBuffer的设备驱动提供了通用的接口. 
1) 全局变量 
struct fb_info *registered_fb[FB_MAX];
int num_registered_fb; 
这两变量记录了所有fb_info 结构的实例,fb_info 结构描述显卡的当前状态,所有设备对应的fb_info 结构都保存在这个数组中,当一个FrameBuffer设备驱动向系统注册自己时,其对应的fb_info 结构就会添加到这个结构中,同时num_registered_fb 为自动加1.

2) fbmem.c 实现了如下函数. 
register_framebuffer(struct fb_info *fb_info);
unregister_framebuffer(struct fb_info *fb_info); 
这两个是提供给下层FrameBuffer设备驱动的接口,设备驱动通过这两函数向系统注册或注销自己。几乎底层设备驱动所要做的所有事情就是填充fb_info结构然后向系统注册或注销它。 
3.xxxfb.c。自己添加的设备驱动文件,如以下等内容。 
static struct fb_ops xxxfb_ops = {
owner: THIS_MODULE,
fb_open: xxxfb_open,/* only if you need it to do something */
fb_release: xxxfb_release, /* only if you need it to do something */
fb_get_fix: fbgen_get_fix,
fb_get_var: fbgen_get_var,
fb_set_var: fbgen_set_var,
fb_get_cmap: fbgen_get_cmap,
fb_set_cmap: fbgen_set_cmap,
fb_pan_display: fbgen_pan_display,
fb_ioctl: xxxfb_ioctl, /* optional */
};

三、framebuffer驱动:

1.首先需要添加下面的代码到fbmem.c 
static struct { 
const char *name; 
int (*init)(void); 
int (*setup)(char*); 
}

fb_drivers[] __initdata = {

#ifdef CONFIG_FB_YOURCARD //红色为添加部分 
{ "driver_name", xxxfb_init, xxxfb_setup }, 
#endif 
2.其次在xxxfb.c 中根据自己的需要重新分配显存大小。例如: 
#define VIDEOMEMSIZE (1*1024*1024) /* 1 MB */ 
再次根据自己的硬件设备修改相应的var 信息。主要修改 
xxxfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) 
下面是函数fb_set_var()的执行步骤: 
1)检测是否必须设定模式
2)设定模式 
3)设定颜色映射 
4) 根据以前的设定重新设置LCD控制器的各寄存器。

四、配置添加驱动: 
1.make menuconfig时,首先进入Character devices,选中里面的Virtualterminal.如果希望控制台在液晶上输出,则选中Support for console on virtual terminal。 
2.退到上一层界面我们就可以看到Console device 的选项,进入后将光标落在Framebuffer Support 上,按回车键进入,在里面选择自己所需要的framebuffer设备即可。 
3.在Advanced low level 中可以配置bpp packed pixel support,然后选中Selectcompiled-in fonts 即可。 
等操作系统运行以后就会在/dev下面看到fb 这个设备。它的major应该是29,第一个设备的minor应该是0。

五、其它: 
编译内核时,选择framebuffer模式,启动时屏幕上有一企鹅图片,不知这是如何造成的这个图片可以去掉或改动吗? 
答:可以将drivers/video/fbcon.c: fbcon_setup()中if (logo) { } 代码去掉。

六、操作framebuffer的主要步骤如下:

1、打开一个可用的FrameBuffer设备;
2、通过mmap调用把显卡的物理内存空间映射到用户空间;
3、更改内存空间里的像素数据并显示;
4、退出时关闭framebuffer设备。
下面的这个例子简单地用framebuffer画了一个渐变的进度条,代码 framebuf.c 如下:
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/mman.h>
inline static unsigned short int make16color(unsigned char r, unsigned char g, unsigned char b)
{
return ((((r >> 3) & 31) << 11) | (((g >> 2) & 63) << 5) | ((b >> 3) & 31) );
}
int main() {
int fbfd = 0;
struct fb_var_screeninfo vinfo;
struct fb_fix_screeninfo finfo;
long int screensize = 0;
char *fbp = 0;
int x = 0, y = 0;
int guage_height = 20, step = 10;
long int location = 0;
// Open the file for reading and writing
fbfd = open("/dev/graphics/fb0", O_RDWR);
if (!fbfd) {
printf("Error: cannot open framebuffer device.\n");
exit(1);
}
printf("The framebuffer device was opened successfully.\n");
// Get fixed screen information
if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo)) {
printf("Error reading fixed information.\n");
exit(2);
}
// Get variable screen information
if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) {
printf("Error reading variable information.\n");
exit(3);
}
printf("sizeof(unsigned short) = %d\n", sizeof(unsigned short));
printf("%dx%d, %dbpp\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel );
printf("xoffset:%d, yoffset:%d, line_length: %d\n", vinfo.xoffset, vinfo.yoffset, finfo.line_length );
// Figure out the size of the screen in bytes
screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;;
// Map the device to memory
fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED,fbfd, 0);
if ((int)fbp == -1) {
printf("Error: failed to map framebuffer device to memory.\n");
exit(4);
}
printf("The framebuffer device was mapped to memory successfully.\n");
//set to black color first
memset(fbp, 0, screensize);
//draw rectangle
y = (vinfo.yres - guage_height) / 2 - 2; // Where we are going to put the pixel
for (x = step - 2; x < vinfo.xres - step + 2; x++) {
location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + (y+vinfo.yoffset) * finfo.line_length;
*((unsigned short int*)(fbp + location)) = 255;
}
y = (vinfo.yres + guage_height) / 2 + 2; // Where we are going to put the pixel
for (x = step - 2; x < vinfo.xres - step + 2; x++) {
location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + (y+vinfo.yoffset) * finfo.line_length;
*((unsigned short int*)(fbp + location)) = 255;
}
x = step - 2;
for (y = (vinfo.yres - guage_height) / 2 - 2; y < (vinfo.yres + guage_height) / 2 + 2; y++) {
location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + (y+vinfo.yoffset) * finfo.line_length;
*((unsigned short int*)(fbp + location)) = 255;
}
x = vinfo.xres - step + 2;
for (y = (vinfo.yres - guage_height) / 2 - 2; y < (vinfo.yres + guage_height) / 2 + 2; y++) {
location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + (y+vinfo.yoffset) * finfo.line_length;
*((unsigned short int*)(fbp + location)) = 255;
}
// Figure out where in memory to put the pixel
for ( x = step; x < vinfo.xres - step; x++ ) {
for ( y = (vinfo.yres - guage_height) / 2; y < (vinfo.yres + guage_height) / 2; y++ ) {
location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + (y+vinfo.yoffset) * finfo.line_length;
if ( vinfo.bits_per_pixel == 32 ) {
*(fbp + location) = 100; // Some blue
*(fbp + location + 1) = 15+(x-100)/2; // A little green
*(fbp + location + 2) = 200-(y-100)/5; // A lot of red
*(fbp + location + 3) = 0; // No transparency
} else { //assume 16bpp
unsigned char b = 255 * x / (vinfo.xres - step);
unsigned char g = 255; // (x - 100)/6 A little green
unsigned char r = 255; // A lot of red
unsigned short int t = make16color(r, g, b);
*((unsigned short int*)(fbp + location)) = t;
}
}
//printf("x = %d, temp = %d\n", x, temp);
//sleep to see it
usleep(200);
}
//clean framebuffer
munmap(fbp, screensize);
close(fbfd);
return 0;
}
复制代码
  注意,在Android环境,framebuffer设备不是象linux一样的 /dev/fb0,而是 /dev/graphics/fb0 ,
fbfd = open("/dev/graphics/fb0", O_RDWR);
打开framebuffer设备,
fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED,
fbfd, 0);
将设备map到一块内存,然后就可以操作这块内存空间来显示你想画的图形了。
最后别忘了关闭设备:
munmap(fbp, screensize);
close(fbfd);


Android下操作FrameBuffer相关推荐

  1. Android下操作联系人(Contacts)

    * 1.读联系人 联系人数据是存储在com.android.providers.contacts应用的数据库中的, 该应用对外提供了ContentProvider 下载原码可以得到Uri和path 查 ...

  2. android下获取无线wif信号、ssid、MAC等操作类

    一个android下获取无线wif信号.ssid.MAC等操作的类. WifiAdmin.java package com.afu; import java.util.List; import and ...

  3. android文件读取工具类,Android 下读取Assets Properties操作封装工具类

    Android 下读取Assets Properties操作封装工具类 发布时间:2018-06-03作者:laosun阅读(2081) 为了方便使用,首先创建BaseApplication类,如下所 ...

  4. 在Android下通过ExifInterface类操作图片的Exif信息

    什么是Exif 先来了解什么是Exif.Exif是一种图像文件格式,它的数据存储于JPEG格式是完全相同的,实际上Exif格式就是JPEG格式头插入了 数码照片的信息,包括拍摄的光圈.快门.平衡白.I ...

  5. Android权限操作之uses-permission详解

    本文实例讲述了Android权限操作之uses-permission.分享给大家供大家参考,具体如下: 我们在安装Android软件的时候,系统会提示该软件所需要的权限,相对于其他系统,android ...

  6. Android下WiFiDisplay功能探究

    1 WiFiDisplay简介 1.1WiFiDisplay概述 WiFiDisplay(WFD)是WiFi联盟在已有技术的基础上,为了加速视/音频的传输分享而提出来的一个新概念.WiFi联盟对此成立 ...

  7. Android下的动画

    ------你需要努力,你还没资格休息----- Android下的动画有三种: tween补间动画.frame帧动画.property属性动画(Android3.0后提出来的).补间动画: Tran ...

  8. android下使用tcpdump抓包

    tcpdump是linux下的抓包工具,在android中没有,需要下载对应的工具. 下载地址:https://www.androidtcpdump.com/android-tcpdump/downl ...

  9. Android下的Linux

    1. Android目录结构 data app:用户安装的应用 data:应用的专属文件夹 system:系统的配置信息,注册表文件 anr:anr异常的记录信息 dev:devices的缩写 存放设 ...

  10. Android下拉刷新开源库对比(转)

    安卓下拉刷新开源库对比 作者:desmond1121 目前仅比对github上star数>1500的下拉刷新开源库,在比较完成之后可能会加入其它有代表性的库. Repo Repo Owner S ...

最新文章

  1. WebDriver 识别反爬虫的原理和破解方法~
  2. linux忘记mysql的密码忘记了_linux忘记mysql密码找回方法
  3. Xamarin效果第二篇之公众号App
  4. java 音频 api_Java中的接口
  5. ubunt Linux nginx,linux ubuntu系统安装nginx教程
  6. 大道至简,凯里亚德酒店成为酒店投资圈万众瞩目的“新”星
  7. 加解密算法 之base64 原理
  8. 脑电的频谱分析和时频分析-EEG Processing and Feature 5
  9. H3C 交换机配置命令
  10. Android中的Apk的加固(加壳)原理解析和实现
  11. hdmi 屏幕旋转 树莓派_树莓派7寸HDMI显示屏使用教程
  12. 【数据科学家】如何成为一名数据科学家?
  13. 学习笔记(02):Java小白修炼手册-工欲善其事必先利其器,掌握Java开发工具
  14. 湍流——湍流积分长度
  15. eclipse各版本说明与区别
  16. python 一键下载酷狗歌单
  17. MT9V034摄像头学习笔记(一)
  18. 河南大学计算机系导师张重生,《大河报》我国首款AI甲骨缀合产品发布,河南大学留学归国人员联谊会会员张重生教授团队主研...
  19. 怎么成为一个合格的ERP系统管理员
  20. ajax上传本地音频文件,使用ajax将音频blob上传到文件夹中

热门文章

  1. Photoshop-图层相关概念-LayerComp-Layers-移动旋转复制图层-复合图层
  2. 7-2 不变初心数 (15 分)
  3. 感动的眼泪流下来。。。。中文ecli…
  4. 【NOIP 2011】 观光公交
  5. 什么软件适合团队协作?团队协作工具排行
  6. Streaming Telemetry翻译学习
  7. 台式计算机如何拆硬盘,台式机如何更换硬盘
  8. Scrapped or attached views may not be recycled. isScrap:false isAttached:true android.support.v7.wid
  9. 亚马逊AWS云服务器 ubuntu系统登陆教程
  10. 干货 | Elasticsearch Nested 数组大小求解,一网打尽!