Linux FrameBuffer(一) —— FrameBuffer是什么?怎么用?

简介: Linux FrameBuffer(一) —— FrameBuffer是什么?怎么用?

一、FrameBuffer是什么

简单理解:

FrameBuffer就是一块显存,你往上面画什么,它就会显示什么。可以将它想象成一个二维平面,由一个个像素的组成,其分辨率宽度和高度的乘积就是整个FrameBuffer的像素点。例如:分辨率为800x600的FrameBuffer,就表示这块显存有600行,每行800个像素点。

补充:

FrameBuffer 也称帧缓存,是 Linux 内核将显存进行抽象后的一块缓存(内存),目的是为了给用户态进程提供一套直接写屏的接口,而不用关心物理显存的位置、换页机制等具体细节。一般在进行Linux系统的图形层开发时需要用到FrameBuffer的相关知识。

FrameBuffer设备文件一般为/dev/fb*,如果系统有多个FrameBuffer设备文件,则表示该系统可能有多个显卡,一个子设备号对应一个显卡。而一些嵌入式芯片平台将FrameBuffer设备与叠加图形层进行关联,下图是海思3531A平台的FrameBuffer设备文件,/dev/fb0表示图形层,/dev/fb3表示鼠标层。

2018122814580746.png

像素格式和分辨率

即使Linux做了抽象,而不需要关系显存的其他细节,但是要往显示器显示图像或者画图,还是需要先设置好一些参数,例如像素格式和分辨率。像素格式包含了一些像素点的信息,如"一个像素点占用多少字节的内存"、“颜色分量起始比特位”、"颜色分量所占比特长度"等等;分辨率则表示了总共有多少个像素点,有了像素格式和分辨率就可以知道这个帧缓存的总大小是多大。


二、FrameBuffer怎么用

2.1 开发流程

前面简单地介绍了FrameBuffer地一些基础知识,最主要的就是要知道 FrameBuffer 是一块缓存(内存),开发过程中就是进行一些简单设置后,可以对这块缓存(内存)直接读写并将写入的内容显示在屏幕上。一般 FrameBuffer 的开发过程如下:

FrameBuffer 开发流程
1.打开设备 #include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int framebuf_fd = open(fbPath, O_RDWR);
2.获取物理显存大小、跨度等固定信息 #include <sys/ioctl.h>
ioctl(framebuf_fd, FBIOGET_FSCREENINFO, &finfo)
3.获取并设置像素位深、像素格式、屏幕高宽等参数 #include <sys/ioctl.h>
ioctl(framebuf_fd, FBIOGET_VSCREENINFO, &vinfo)
ioctl(framebuf_fd, FBIOPUT_VSCREENINFO, &vinfo)
4.映射物理显存到用户虚拟内存空间 #include <sys/mman.h>
fbMapMem=(char*)mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, framebuf_fd, 0);
5.操作虚拟内存,完成具体绘制任务 fillRect(0xffff0000,0,0,30,30);
6.解除显存映射 #include <sys/mman.h>
munmap(fbMapMem, size);
7.关闭设备 #include <unistd.h>
close(framebuf_fd);

2.2 FrameBuffer画图最简单代码

跟据上面的开发流程,我写了下面这个在Linux的FrameBuffer上画图的.c文件,主要是更好地理解上面的开发流程,实际使用FrameBuffer应该会复杂一点,但流程差不多。可以直接把这个.c文件复制到Ubuntu或其他Linux平台编译,通过后运行,会看到左上角一直在画30*30大小的方块:

2018122814580746.png

// framebuffer.c
#include <stdio.h>
#include <linux/fb.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
unsigned int fb_byteW=0, fb_byteH=0; // 用字节表示的宽度和高度
unsigned int bytesPerPixel = 0; // 一个像素占用的字节数
char *fbMapMem = NULL;
void fillRect(int color, int x, int y, int w, int h)
{
  int i=0, j=0, offset = 0;
  if(bytesPerPixel==4)
  {
    for(i=0; i<h; i++)
    {
      offset = x*bytesPerPixel + (y+i)*fb_byteW;
      for(j=0; j<w; j++)
      {
        int *tmp = (int *)&fbMapMem[offset];
        *tmp = color;
        offset += bytesPerPixel;
      }
    }
  }
  else
    printf("error bytesPerPixel=%d\n", bytesPerPixel);
}
int main(int argc, char *argv[])
{
  // 1.打开设备
  char fbPath[64] = "/dev/fb0";
  int framebuf_fd = open(fbPath, O_RDWR);
  if ( framebuf_fd < 0 ) {
        printf("[%s:%d] open %s error \n", __FILE__,__LINE__,fbPath);
        return -1;
    }
  // 2.获取设备固定参数
  struct fb_fix_screeninfo finfo;
  if (ioctl(framebuf_fd, FBIOGET_FSCREENINFO, &finfo) < 0)
    {
        fprintf(stderr, "ioctl FBIOGET_FSCREENINFO err \r\n");
        return -1;
    }
  // 3.1 获取虚拟参数
  struct fb_var_screeninfo vinfo;
    if (ioctl(framebuf_fd, FBIOGET_VSCREENINFO, &vinfo) < 0)
    {
        fprintf(stderr, "ioctl FBIOGET_VSCREENINFO err \r\n");
        return -1;
    }
  // 3.2 设置虚拟参数
  bytesPerPixel = vinfo.bits_per_pixel / 8;
  vinfo.xres = vinfo.xres_virtual = finfo.line_length/bytesPerPixel;
  if (ioctl(framebuf_fd, FBIOPUT_VSCREENINFO, &vinfo) < 0)
    {
        fprintf(stderr, "ioctl FBIOPUT_VSCREENINFO err \r\n");
        return -1;
    }
  fb_byteW = vinfo.xres * bytesPerPixel;
  fb_byteH = vinfo.yres * bytesPerPixel;
  printf("[line:%d] line_length=%d res=[%dx%d], Bpp=%d ByteWH=[%d %d]\n",__LINE__,finfo.line_length,vinfo.xres,vinfo.yres,bytesPerPixel,fb_byteW, fb_byteH);
  // 4.映射物理显存到用户虚拟内存空间
  unsigned long size = vinfo.xres*vinfo.yres*bytesPerPixel;
    if (NULL == (fbMapMem=(char *)mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, framebuf_fd, 0)) )
    {
        fprintf(stderr, "mmap size %ld err \r\n", size);
        return -1;
    }
  // 5.操作虚拟内存,完成具体绘制任务,每隔一秒画一个颜色的正方形
  while(1)
  {
    fillRect(0xff0000,0,0,30,30);// 红色
    sleep(1);
    fillRect(0x00ff00,0,0,30,30);// 绿色
    sleep(1);
    fillRect(0x0000ff,0,0,30,30);// 蓝色
    sleep(1);
  }
  // 6.解除显存映射
  munmap(fbMapMem, size);
  // 7.关闭设备
  close(framebuf_fd);
  return 0;
}

要运行上面这个程序的话,一定要系统里有/dev/fb0的文件,如果你是比较旧的Ubuntu系统,且没有/dev/fb0文件的话,可以参考这篇文章:虚拟机的 Ubuntu 没有 /dev/fb0 的解决办法

如果文章对你有用的话,点个赞让我知道 *_^

目录
相关文章
|
4天前
|
Linux Android开发
嵌入式linux中Framebuffer 驱动程序框架分析
嵌入式linux中Framebuffer 驱动程序框架分析
33 0
|
4天前
|
编解码 Ubuntu Linux
Linux应用开发基础知识——Framebuffer 应用编程(四)
Linux应用开发基础知识——Framebuffer 应用编程(四)
46 0
Linux应用开发基础知识——Framebuffer 应用编程(四)
|
Linux Android开发 芯片
Linux驱动分析之Framebuffer驱动
前面我们了解了LCD的基本架构《Linux驱动分析之LCD驱动架构》,接下来我们拿个具体的实例来分析分析。这样可以了解其大概是如何使用和工作的。
|
编解码 Linux
Linux 应用基础 Framebuffer应用编程
在 Linux应用基础中,Framebuffer 驱动程序主要用来控制 LCD。今天带大家来了解一下如何通过 Framebuffer 来编程 LCD。 在此之前,我们要先了解一下 Framebuffer 和 LCD。
162 0
|
编解码 Linux
Linux下的Framebuffer编程
Linux下的Framebuffer编程
101 0
|
编解码 Ubuntu Linux
Linux FrameBuffer(三)- struct fb_fix_screeninfo 和 struct fb_var_screeninfo 详解
Linux FrameBuffer(三)- struct fb_fix_screeninfo 和 struct fb_var_screeninfo 详解
323 0
|
编解码 Ubuntu Linux
Linux FrameBuffer(二)- VMware虚拟机的Ubuntu系统FrameBuffer画图
Linux FrameBuffer(二)- VMware虚拟机的Ubuntu系统FrameBuffer画图
253 0
Linux FrameBuffer(二)- VMware虚拟机的Ubuntu系统FrameBuffer画图
|
编解码 Ubuntu Linux
linux/鸿蒙开发(基于IMX6ULL)开发 (十三)Framebuffer应用编程
linux/鸿蒙开发(基于IMX6ULL)开发 (十三)Framebuffer应用编程
219 2
linux/鸿蒙开发(基于IMX6ULL)开发 (十三)Framebuffer应用编程
|
编解码 Linux Go
Linux内核的framebuffer相关的内核代码注释
版权声明:您好,转载请留下本人博客的地址,谢谢 https://blog.csdn.net/hongbochen1223/article/details/49259589 由于现在正...
1220 0
|
Linux SDN
嵌入式Linux基于framebuffer的jpeg格式本地LCD屏显示
<p style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;">在基于Linux的视频监控采集系统中,摄像头采集到的一帧视频图像数据一般都是经过硬件自动压缩成jpeg格式的,然后再保存到摄像头设备的缓冲区.如果要把采集到的jpeg格式显示在本地LCD屏上,由于我们的Linux系
3181 0