[转]基于FrameBuffer的直接写屏

2024-01-25 16:18
文章标签 直接 framebuffer 写屏

本文主要是介绍[转]基于FrameBuffer的直接写屏,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1.将FrameBuffer配置成800x600x16色的显示模式
在/boot/grub/menu.lst中的kernel加入vga=0x314
//test.c

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc,char **argv){
 int fb_fd=0;
 char *fbdev="/dev/fb0";
 if((fd_fd=open(fbdev,O_RDWR))<0){
  printf("open FrameBuffer device failed."n");
  return -1;
 }
 printf("open FrameBuffer device successfully!"n");
 close(fb_fd);
}


编译后执行一下,看看当前内核是否支持FrameBuffer机制.
设备打开成功后要获取相当的参数,使用ioctl,会填充以下结构体,
在linux/fb.h中定义的
struct fb_fix_screeninfo
struct fb_var_screeninfo
struct fb_cmap
从fs.h中可看出

#define FBIOGET_VSCREENINFO 0x4600
#define FBIOGET_FSCREENINFO 0x4602

我们就用这两条命令获取相当的参数信息
//test.c

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/fb.h>
int main(int argc,char **argv){
 int fb_fd=0;
 char *env="/dev/fb0";
 struct fb_fix_screeninfo fb_fixinfo;
 struct fb_var_screeninfo fb_varinfo;
 if((fb_fd=open(env,O_RDWR))<0){
  printf("Error:open FrameBuffer device:%s"n",env);
  return -1;
 }else{
  printf("OK:open FrameBuffer device:%s"n",env);
 }
 if(ioctl(fb_fd,FBIOGET_FSCREENINFO,&fb_fixinfo)==-1){
  printf("Error:FBIOGET_FSCREENINFO"n");
  goto fail;
 }
 printf("ioctl FBIOGET_FSCREENINFO ok"n");
 printf("id=%s"n",fb_fixinfo.id);
 printf("smem_start=%#x"n",fb_fixinfo.smem_start);
 printf("mem_len=%d"n",fb_fixinfo.smem_len);
 printf("type=%d"n",fb_fixinfo.type);
 printf("type_aux=%d"n",fb_fixinfo.type_aux);
 printf("visual=%d"n",fb_fixinfo.visual);
 printf("xpanstep=%d"n",fb_fixinfo.xpanstep);
 printf("ypanstep=%d"n",fb_fixinfo.ypanstep);
 printf("ywrapstep=%d"n",fb_fixinfo.ywrapstep);
 printf("line_length=%d"n",fb_fixinfo.line_length);
 printf("mmio_start=%#x"n",fb_fixinfo.mmio_start);
 printf("mmio_len=%#x"n",fb_fixinfo.mmio_len);
 printf("accel=%d"n",fb_fixinfo.accel);
 printf("reserved[0]=%d"n",fb_fixinfo.reserved[0]);
 printf("reserved[1]=%d"n",fb_fixinfo.reserved[1]);
 printf("reserved[2]=%d"n",fb_fixinfo.reserved[2]);
 if(ioctl(fb_fd,FBIOGET_VSCREENINFO,&fb_varinfo)==-1){
  printf("Error:ioctl:FBIOGET_VSCREENINFO"n");
  goto fail;
 }
 printf("ioctl FBIOGET_VSCREENINFO ok"n");
 printf("xres=%d"n",fb_varinfo.xres);
 printf("yres=%d"n",fb_varinfo.yres);
 printf("xres_virtual=%d"n",fb_varinfo.xres_virtual);
 printf("yres_virtual=%d"n",fb_varinfo.yres_virtual);
 printf("xoffset=%d"n",fb_varinfo.xoffset);
 printf("yoffset=%d"n",fb_varinfo.yoffset);
 printf("bits_per_pixel=%d"n",fb_varinfo.bits_per_pixel);
 printf("grayscale=%d"n",fb_varinfo.grayscale);
 printf("red=%#x"n",fb_varinfo.red);
 printf("green=%#x"n",fb_varinfo.green);
 printf("blue=%#x"n",fb_varinfo.blue);
 printf("transp=%d"n",fb_varinfo.transp);
 printf("nonstd=%d"n",fb_varinfo.nonstd);
 printf("activate=%d"n",fb_varinfo.activate);
 printf("height=%d"n",fb_varinfo.height);
 printf("width=%d"n",fb_varinfo.width);
 printf("accel_flags=%d"n",fb_varinfo.accel_flags);
 printf("pixclock=%d"n",fb_varinfo.pixclock);
 printf("left_margin=%d"n",fb_varinfo.left_margin);
 printf("right_margin=%d"n",fb_varinfo.right_margin);
 printf("upper_margin=%d"n",fb_varinfo.upper_margin);
 printf("lower_margin=%d"n",fb_varinfo.lower_margin);
 printf("hsync_len=%d"n",fb_varinfo.hsync_len);
 printf("vsync_len=%d"n",fb_varinfo.vsync_len);
 printf("sync=%d"n",fb_varinfo.sync);
 printf("vmode=%d"n",fb_varinfo.vmode);
 printf("rotate=%d"n",fb_varinfo.rotate);
 printf("reserved[0]=%d"n",fb_varinfo.reserved[0]);
 printf("reserved[1]=%d"n",fb_varinfo.reserved[1]);
 printf("reserved[2]=%d"n",fb_varinfo.reserved[2]);
 printf("reserved[3]=%d"n",fb_varinfo.reserved[3]);
 printf("reserved[4]=%d"n",fb_varinfo.reserved[4]);
 
 close(fb_fd);
 return 0;
fail:
 close(fb_fd);
 return -1;
}


从输出结果来看xres=800,yres=600,从这里可以看出这个FrameBuffer的最大值为800x600
得到framebuffer的信息后,我们开辟一段内存,然后映射framebuffer的内存,
这样当向这段内存写入信息时,framebuffer中就会写入相同的数据,也就会有数据表示的图像显示在屏幕上。
例:在屏幕上显示一个渐变窗体

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <errno.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
int flush_screen(char *buf,char *framebuf,int width,int height);
int main(int argc, char *argv[])
{
        int fb_fd=0;
        struct fb_fix_screeninfo fb_fixinfo;
        struct fb_var_screeninfo fb_varinfo;
    char *fb_addr;
    unsigned long fb_size;
    char *buffer;
    int i=0;
       if((fb_fd=open("/dev/fb0", O_RDWR))<0){
         printf("open framebuffer device failed."n");
         return -1;
       }
    printf("open framebuffer device ok"n");
     
        if(ioctl(fb_fd, FBIOGET_FSCREENINFO, &fb_fixinfo) == -1)
        {
                printf("ioctl FBIOGET_FSCREENINFO failed."n");
                return -1;
        }
    printf("ioctl FBIOGET_FSCREENINFO ok"n");
        if(ioctl(fb_fd, FBIOGET_VSCREENINFO, &fb_varinfo) == -1)
        {
                printf("ioctl FBIOGET_VSCREENINFO failed."n");
                return -1;
        }
    printf("ioctl FBIOGET_VSCREENINFO ok"n");
        fb_size = fb_varinfo.yres * fb_fixinfo.line_length;   //整个framebuffer的大小
        fb_addr = (char *)mmap(NULL, fb_size, PROT_READ|PROT_WRITE,MAP_SHARED, fb_fd, 0); //将framebuffer的物理地址映射到进程地址空间
        buffer=(char*)malloc(fb_varinfo.yres * fb_fixinfo.line_length); //申请一个缓冲区,采用双缓冲方式
    for(i=0;i<=0xff;i+=0x0f){
          memset(buffer,i,fb_varinfo.yres * fb_fixinfo.line_length);
          flush_screen(buffer,fb_addr,fb_varinfo.xres,fb_varinfo.yres);
      sleep(1);
    }
        if (!fb_addr)
                exit(1);
        free(buffer);
        return 0;
}

int flush_screen(char *buf,char *framebuf,int width,int height)
{
                char *t_data = buf;
                char *t_fb_addr = framebuf;
                int bytew= width<<1;
                while(--height >= 0)
                {
                        memcpy(t_fb_addr,t_data,bytew);
                        t_fb_addr += width;
                        t_data += width;
                }
}


编译后,运行看一下结果,尽量在字符模式下运行
vi /etc/inittab将运行级别改为3
重启后,运行一下看看结果。

这篇关于[转]基于FrameBuffer的直接写屏的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/643829

相关文章

[项目][CMP][直接向堆申请页为单位的大块内存]详细讲解

目录 1.系统调用 1.系统调用 Windows和Linux下如何直接向堆申请页为单位的大块内存: VirtualAllocbrk和mmap // 直接去堆上按页申请空间static inline void *SystemAlloc(size_t kpage){#ifdef _WIN32void *ptr = VirtualAlloc(0, kpage << 13,

PageOfficeCtrl支持直接打开服务器磁盘文件

一般来说,PageOfficeCtrl控件的WebOpen方法的第一个参数是待打开文档的URL,此URL可以是相对于当前页面的相对URL,也可以是相对于整个网站根的相对URL,还可以是http开头的完整URL,但是这个URL必须是当前网站的URL,不能跨域。 现在为了更加方便开发者编程,WebOpen支持打开服务器磁盘文件。也就是说,第一个参数可以写成服务器文件的绝对磁盘路径。例如: P

最直接显示 ubuntu 版本号的命令

有时候去看ubuntu版本号,去网上查,很多文章都列出一堆命令,复制命令运行一下,都是打印一些不相关的信息,我只是想看ubuntu版本号而已,能否直接列出版本号就可以了。 有,下面这条命令就是直接的打印出ubuntu版本号, 没有多余信息 lsb_release -a

【UVA】10651-Pebble Solitaire(直接递归或者记忆化)

不知道这个题UVA的数据是怎么的,用2个方法交了,第一次直接递归,第二次记忆化剪枝,时间竟然一样!? 直接郁闷了,简单的二进制表示状态和二进制运算。 14145176 10651 Pebble Solitaire Accepted C++ 0.009 2014-09-04 09:18:21 #include<cstdio>#include<algorithm>#inclu

Anthropic 创始人 Dario Amodei 谈:关于护城河与风险,AI 大很难直接替代人

护城河的迷思   近期,Anthropic创始人Dario Amodei与投资人Erik Torenberg进行了一场引人关注的对话。他们探讨了AI的护城河与潜在风险。话说,护城河就像酒水的保质期,过了时间就得小心别翻车。Amodei提到,AI虽有强大的潜力,但短期内难以完全替代人类的智慧。这可让很多人松了一口气,毕竟机器发热总比人心复杂,听着都觉得不舒服。 聪明与控制的博弈   Dar

GitHub:代码是程序员沟通最直接的手段

如果不是 Andreessen horowitz 的投资,估计 GitHub 很难被福布斯、CNN、纽约时报等传统媒体注意到。普通大众之前不了解这个工具,是因为它距离记者的世界太远了——GitHub 是一个程序员所使用的托管项目的服务。 但在一些程序员眼里,它不仅是托管项目的地方,还是“开源”项目的大本营,而且是提高程序员“技术水平”和“技术品味”的地方,更是一个程序员社交的地方。

Base64编码 及 在HTML中用Base编码直接显示图片或嵌入其他文件类型

1.为什么要用到BASE64编码的图片信息      Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一。Base64 主要不是加密,它主要的用途是把一些二进制数转成普通字符用于网络传输。由于一些二进制字符在传输协议中属于控制字符,不能直接传送需要转换一下。最常见的用途是作为电子邮件或WebService附件的传输编码.  2.base64编码定义    目前的internet

Java虚拟机--直接内存

文章引用: 深入理解Java虚拟机 直接内存(Direct Memory)并不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域.但是这部分内存也被频繁的使用,而且也可能导致OutOfMemoryError异常出现. 在JDK1.4中新加入NIO(New Input/Output)类,引入了一种基于通道(Channel)与缓冲区(Buffer)的I/O方式

开发app在android6.0运行直接退出解决(二)

上篇文章:http://blog.csdn.net/u013408979/article/details/52289534 只简单的解决能在android6.0运行,但没有根本的解决问题。 下面介绍解决方法: 参考 http://xdeveloper.cn/gai-jin-ban-android6-0quan-xian-gua-pei-bi-ni-xiang-de-huan-yao-ji

【数据结构】——直接选择排序

前言:在之前文章当中,我们了解过了堆排序,而堆排序是属于选择排序的一种,下面我们将继续了解直接选择排序。 堆排序的链接:堆排序以及向上、向下调整算法的时间复杂度推导及实现(超详细)-CSDN博客 选择排序 选择排序的基本思想:每⼀次从待排序的数据元素中选出最小(或最大)的⼀个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。 直接选择排序 1. 在元素集合 array[i