static GGLContext *gr_context = 0;
static GGLSurface gr_framebuffer[2];
static unsigned gr_active_fb = 0; static int gr_fb_fd = -1;
static int gr_vt_fd = -1; static struct fb_var_screeninfo vi;
struct fb_fix_screeninfo fi;
// 得到framebuffer的相关信息(可变或固定的)
// 及映射数据区域
static int get_framebuffer(GGLSurface *fb)
{
int fd;
void *bits;
//将尝试打开两个位置的设备文件
fd = open("/dev/graphics/fb0", O_RDWR);
if (fd < 0) {
printf("cannot open /dev/graphics/fb0, retrying with /dev/fb0\n");
if ((fd = open("/dev/fb0", O_RDWR)) < 0) {
perror("cannot open /dev/fb0");
return -1;
}
}
//得到framebuffer的相关信息
if(ioctl(fd, FBIOGET_FSCREENINFO, &fi) < 0) {
perror("failed to get fb0 info");
return -1;
} if(ioctl(fd, FBIOGET_VSCREENINFO, &vi) < 0) {
perror("failed to get fb0 info");
return -1;
} dumpinfo(&fi, &vi);
// kernel缓冲区映射到用户空间
bits = mmap(0, fi.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if(bits == MAP_FAILED) {
perror("failed to mmap framebuffer");
return -1;
} fb->version = sizeof(*fb);
fb->width = vi.xres;
fb->height = vi.yres;
fb->stride = fi.line_length / (vi.bits_per_pixel >> 3);
fb->data = bits;
fb->format = GGL_PIXEL_FORMAT_RGB_565;
// 双缓冲
fb++; fb->version = sizeof(*fb);
fb->width = vi.xres;
fb->height = vi.yres;
fb->stride = fi.line_length / (vi.bits_per_pixel >> 3);
fb->data = (void*) (((unsigned) bits) + vi.yres * vi.xres * 2);
fb->format = GGL_PIXEL_FORMAT_RGB_565; return fd;
}
// 这里假设framebuffer是双缓冲,理论上应当判断下
// 不能直接断定是否双缓冲
static void set_active_framebuffer(unsigned n)
{
if(n > 1) return;
// framebuffer的缓冲区大小,至少要可以两张图片的容量
vi.yres_virtual = vi.yres * 2;
vi.yoffset = n * vi.yres;
if(ioctl(gr_fb_fd, FBIOPUT_VSCREENINFO, &vi) < 0) {
fprintf(stderr,"active fb swap failed!\n");
} else
printf("active buffer: %d\n", n);
}
// 导出framebuffer的相关信息(x, y , bits_per_pixel等)
static void dumpinfo(struct fb_fix_screeninfo *fi, struct fb_var_screeninfo *vi)
{
fprintf(stderr,"vi.xres = %d\n", vi->xres);
fprintf(stderr,"vi.yres = %d\n", vi->yres);
fprintf(stderr,"vi.xresv = %d\n", vi->xres_virtual);
fprintf(stderr,"vi.yresv = %d\n", vi->yres_virtual);
fprintf(stderr,"vi.xoff = %d\n", vi->xoffset);
fprintf(stderr,"vi.yoff = %d\n", vi->yoffset);
fprintf(stderr, "vi.bits_per_pixel = %d\n", vi->bits_per_pixel); fprintf(stderr, "fi.line_length = %d\n", fi->line_length); }
int gr_init(void)
{
int fd = -1;
// 不太明白,为什么要打开tty0,测试的时候不执行也没有影响
if (!access("/dev/tty0", F_OK)) {
fd = open("/dev/tty0", O_RDWR | O_SYNC);
if(fd < 0)
return -1; if(ioctl(fd, KDSETMODE, (void*) KD_GRAPHICS)) {
close(fd);
return -1;
}
}
//初始化,framebuffer 数据结构
gr_fb_fd = get_framebuffer(gr_framebuffer); if(gr_fb_fd < 0) {
if (fd >= 0) {
ioctl(fd, KDSETMODE, (void*) KD_TEXT);
close(fd);
}
return -1;
} gr_vt_fd = fd; /* start with 0 as front (displayed) and 1 as back (drawing) */
gr_active_fb = 0;
set_active_framebuffer(0); return 0;
}
// 退出,关闭文件等
void gr_exit(void)
{
close(gr_fb_fd);
gr_fb_fd = -1; if (gr_vt_fd >= 0) {
ioctl(gr_vt_fd, KDSETMODE, (void*) KD_TEXT);
close(gr_vt_fd);
gr_vt_fd = -1;
}
}
int gr_fb_width(void)
{
return gr_framebuffer[0].width;
} int gr_fb_height(void)
{
return gr_framebuffer[0].height;
}
uint16_t red = 0xf800;
uint16_t green = 0x07e0;
uint16_t blue = 0x001f;
// 在缓冲区上绘制图片,一共四个区域
|--|--|
| | |
|--|--|
| | |
-----
void draw_grid(int w, int h, uint16_t* loc) {
int i, j;
int v;
int stride = fi.line_length / (vi.bits_per_pixel >> 3); for (j = 0; j < h/2; j++) {
for (i = 0; i < w/2; i++)
loc[i + j*(stride)] = red;
for (; i < w; i++)
loc[i + j*(stride)] = green;
}
for (; j < h; j++) {
for (i = 0; i < w/2; i++)
loc[i + j*(stride)] = blue;
for (; i < w; i++)
loc[i + j*(stride)] = 0xffff;
} }
// 清空缓冲区数据都为00,视觉上表现为纯黑色
void clear_screen(int w, int h, uint16_t* loc)
{
int i,j;
int stride = fi.line_length / (vi.bits_per_pixel >> 3); for (j = 0; j < h; j++)
for (i = 0; i < w; i++)
loc[i + j*(stride)] = 0x0000;
}
int main(int argc, char **argv) {
int w;
int h;
int id = 0;
gr_init();
w = vi.xres;
h = vi.yres;
// 清空缓冲区数据都为00
clear_screen(w, h, (uint16_t *)gr_framebuffer[0].data);
clear_screen(w, h, (uint16_t *)gr_framebuffer[1].data); if (argc > 2) {
w = atoi(argv[1]);
h = atoi(argv[2]);
} if (argc > 3)
id = !!atoi(argv[3]);
// 绘制图片
draw_grid(w, h, (uint16_t *)gr_framebuffer[id].data);
//显示双缓冲的内容,中间和最后加个sleep(),效果会更明显
set_active_framebuffer(!id);
set_active_framebuffer(id); return 0;
}

测试framebuffer的更多相关文章

  1. Android6.0.1 移植:显示系统(一)--测试framebuffer

    #include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/sta ...

  2. S04_CH01_搭建工程移植LINUX/测试EMMC/VGA

    S04_CH01_搭建工程移植LINUX/测试EMMC/VGA 1.1概述: 本章内容是在已经提供安装了VIVADO2015.4 的ubuntu系统下,进行.大家可以下周我们已经提供的虚拟机镜像,我们 ...

  3. [IMX6]Android6.0移植和分析

    0. 知识点 中断(设备树) [IMX6]设备树分析--dts 1. 编译 Android6.0内核移植(1):分析编译日志 Android6.0内核移植(2):kernel编译内核 单独烧录kern ...

  4. Framebuffer原理、使用、测试系列文章,非常好的资料,大家一起学习

    转载:http://blog.csdn.net/tju355/article/details/6881372 *一.FrameBuffer的原理* FrameBuffer 是出现在 2.2.xx 内核 ...

  5. 全网络最正确的让 Linux 开机进入字符界面的方法及设置 FrameBuffer 分辨率的方法

    引言 这个标题有点长,是为了在标题中就把问题说清楚,以便搜索引擎能够把有需要的朋友准确地带到我这里来.目前在网络上,很多关于 Linux 方面的知识是过时的和错误的.我标题中指出的两个知识点就是其中的 ...

  6. python将图片转换为Framebuffer裸数据格式(终端显示图片)

    要在ubuntu终端显示图片或者在板子的LCD显示图片,Framebuffer是一个简单易用的接口,直接写入像素信息即可. 但普通的图片带有头部信息或者编码格式不同,直接送入Framebuffer是显 ...

  7. 提取bmp图片的颜色信息,可直接framebuffer显示(c版本与python版本)

    稍微了解了下linux的framebuffer,这是一种很简单的显示接口,直接写入像素信息即可 配置好的内核,会有/dev/fbn 的接口,于是想能否提前生成一个文件,比如logo.fb,里面仅包含像 ...

  8. framebuffer应用编程实践

    framebuffer的使用主要包括4个部分: (1):首先需要打开设备文件 /dev/fb0. (2):获取设备的信息.包括可变信息和不可变信息,分别使用两个结构体来进行封装,这两个结构体在 < ...

  9. 【转】Linux Framebuffer

    全面的framebuffer详解 一.FrameBuffer的原理 FrameBuffer 是出现在 2.2.xx 内核当中的一种驱动程序接口. Linux是工作在保护模式下,所以用户态进程是无法象D ...

随机推荐

  1. 自定义UIViewController与xib文件关系深入分析

    6月14日 上海 OSC 源创会开始报名啦,有很多机械键盘送哦!!! 用xcode模板向工程加入UIViewController sub class的时候,如果选中了with xib for inte ...

  2. ZOJ 2972 Hurdles of 110m 【DP 背包】

    一共有N段过程,每段过程里可以选择 快速跑. 匀速跑 和 慢速跑 对于快速跑会消耗F1 的能量, 慢速跑会集聚F2的能量 选手一开始有M的能量,即能量上限 求通过全程的最短时间 定义DP[i][j] ...

  3. ORACLE存储过程笔记3

    ORACLE存储过程笔记3 流程控制 1.条件   if expression thenpl/sql or sqlend if;   if expression thenpl/sql or sqlel ...

  4. Image控件

    前台代码: <asp:Image ID="Image1" runat="server" /> 后台代码; protected void Page_L ...

  5. QT序列化操作(比较复杂和完善)

    应用需求: 在网盘开发过程中有这样一个需求,即对文件版本进行控制,即记录文件版本的更替信息,这里说的更替信息仅仅是记录不同时刻的文件变化,即文件的增.删.改.重命名等操作.在每个待监控的目录下都会保存 ...

  6. 在SSH框架中使用Spring的好处(转)

    以下是我总结下今天笔试中SSh中的总结: 在SSH框架中spring充当了管理容器的角色.我们都知道Hibernate用来做持久层,因为它将JDBC做了一个良好的封装,程序员在与数据库进行交互时可以不 ...

  7. activity横屏竖屏的切换

    原理: 其实总结起来,我们可以得到以下的一些结论 1.当内存不足(不容易模拟).切屏时会调用onSaveInstanceState().onRestoreInstanceState()方法 对于onS ...

  8. mysq Point类型 查询和插入操作:insert和select

    首先,创建一个表名为geometry2的表,然后增加一个名为gemo的point类型的字段. insert方法有4中,例如以下所看到的://============================== ...

  9. 在Myeclipse中安装java Decompiler

    由于在myeclipse中的Help选项中没有Install New Software,所以在eclipse中安装插件的方法并不适应于Myeclipse,但是我们可以通过点击Windows->P ...

  10. java--函数练习

    /* 1,定义一个功能,用于打印矩形 1,定义一个打印九九乘法表功能的函数 */ class FunctionTest { public static void main(String[] args) ...