Linux framebuffer 编程入门:直接操作显存画图

在 Linux 下,我们可以通过 framebuffer(帧缓冲) 技术直接在屏幕上画图,而不需要复杂的 GUI 库。

1. 什么是 framebuffer?

framebuffer 是 Linux 内核为图形显示提供的一套接口,允许用户空间程序直接访问显存数据。

通过 /dev/fb0 这个设备文件,我们可以获取屏幕参数、映射显存,然后直接修改像素。

2. 基本流程

操作 framebuffer 的基本步骤如下:

  1. 打开显示设备

    复制代码
    int fd = open("/dev/fb0", O_RDWR);
  2. 获取显示设备参数

    • 分辨率(xresyres

    • 虚拟分辨率(xres_virtualyres_virtual

    • 像素格式(RGB888、RGB565等)

      ioctl(fd, FBIOGET_VSCREENINFO, &vinfo);

  3. 建立显存映射

    复制代码
    unsigned int *pmem = mmap(
        NULL, screensize, PROT_READ | PROT_WRITE,
        MAP_SHARED, fd, 0
    );
  4. 写入像素值

    • 例如在 (x, y) 位置画一个像素:

      复制代码
      *(pmem + y * vinfo.xres_virtual + x) = 0x00FF0000; // 红色
  5. 解除映射

    复制代码
    munmap(pmem, screensize);
  6. 关闭设备

    复制代码
    close(fd);

3. 显存与坐标的关系

假设屏幕分辨率是 800 × 600,像素格式是 RGB888(4 字节对齐):

(x, y) 像素在显存中的偏移:

复制代码
偏移 = y * xres_virtual + x

例如 (400, 300) 的像素地址:

复制代码
pmem + 800 * 300 + 400

对应像素值示例:

复制代码
0x00FF0000  → 红色
0x0000FF00  → 绿色
0x000000FF  → 蓝色

4. mmap 参数解析

复制代码
void *mmap(void *addr, size_t length, int prot, int flags,
           int fd, off_t offset);

addr:用户空间起始地址

一般传 NULL 让系统自动分配

length:映射的长度(字节数)

prot:映射区域权限

PROT_READ 允许读

PROT_WRITE 允许写

flags :常用 MAP_SHARED(修改会同步到显存)

fdopen("/dev/fb0", O_RDWR) 得到的文件描述符

offset:映射偏移量(一般 0 表示从显存开头)

返回值:

成功 → 映射的用户空间首地址

失败 → MAP_FAILED

5. 像素格式

RGB888:每像素 3 字节(但一般对齐到 4 字节)

RGB565:每像素 2 字节常见 24 位

RGB888 存储顺序:

RGB(红绿蓝)

BGR(蓝绿红)例如纯白色:

复制代码
R: 0xFF
G: 0xFF
B: 0xFF

6. 示例:画两个点

复制代码
// 红色
unsigned int red = 0x00FF0000;

// 在 (100, 100) 画一个像素
*(pmem + 100 * vinfo.xres_virtual + 100) = red;

// 在 (400, 300) 画一个像素
*(pmem + 300 * vinfo.xres_virtual + 400) = red;

总结

framebuffer 编程直接操作显存,适合做嵌入式 UI、简单绘图、屏幕测试等场景。掌握了分辨率、像素格式和显存映射后,就可以自由地绘制任意图形了。