一、核心概念解析
1. FrameBuffer 定义
- 硬件抽象层:将显卡显存抽象为字符设备
/dev/fbX
- 核心功能:允许用户空间直接操作显示缓冲区
- 设备路径:
- 主显示器:
/dev/fb0
- 多显示器:
/dev/fb1
, /dev/fb2
等
2. 技术特点
特性 | 说明 |
---|
设备无关性 | 统一接口适配不同显卡 |
直接内存操作 | 通过mmap映射显存到用户空间 |
像素级控制 | 支持任意分辨率/色深配置 |
无硬件加速 | 纯CPU操作,适合简单图形需求 |
二、核心数据结构
1. 屏幕信息结构体
#include <linux/fb.h>
struct fb_var_screeninfo { // 可变参数
__u32 xres; // 可见水平分辨率
__u32 yres; // 可见垂直分辨率
__u32 bits_per_pixel; // 每像素位数 (bpp)
__u32 red_offset; // 红色分量偏移
__u32 green_offset; // 绿色分量偏移
__u32 blue_offset; // 蓝色分量偏移
};
struct fb_fix_screeninfo { // 固定参数
char id[16]; // 设备标识字符串
unsigned long smem_len; // 显存总长度
};
三、关键系统调用
1. 设备信息获取
int ioctl(int fd, unsigned long request, ...);
// 获取可变参数
ioctl(fd, FBIOGET_VSCREENINFO, &var_info);
// 获取固定参数
ioctl(fd, FBIOGET_FSCREENINFO, &fix_info);
2. 内存映射操作
// 映射显存
void *mmap(void *addr, size_t length, int prot,
int flags, int fd, off_t offset);
// 示例:映射32位色深屏幕
unsigned int *fb_mem = mmap(NULL,
var_info.xres * var_info.yres * 4,
PROT_READ | PROT_WRITE,
MAP_SHARED,
fb_fd, 0);
// 解除映射
munmap(fb_mem, fix_info.smem_len);
四、颜色格式解析
1. 常见像素格式
格式 | 数据位宽 | 颜色分量分布 | 应用场景 |
---|
RGB888 | 32-bit | 0x00RRGGBB (8-8-8) | 高色彩精度显示 |
RGB565 | 16-bit | R(5-bit) G(6-bit) B(5-bit) | 嵌入式设备 |
ARGB8888 | 32-bit | 0xAARRGGBB | 带透明度图形 |
五、设备初始化流程
1. 设备打开与参数获取
int init_fb(char *devname) {
// 1. 打开帧缓冲设备
int fd = open(devname, O_RDWR);
if (fd == -1) {
perror("FrameBuffer open failed");
return -1;
}
// 2. 获取可变屏幕参数
struct fb_var_screeninfo vinf;
if (ioctl(fd, FBIOGET_VSCREENINFO, &vinf) == -1) {
perror("ioctl FBIOGET_VSCREENINFO failed");
close(fd);
return -1;
}
// 3. 计算映射内存大小(包含虚拟分辨率)
size_t len = vinf.xres_virtual * vinf.yres_virtual *
(vinf.bits_per_pixel / 8);
// 4. 内存映射(需考虑字节对齐)
unsigned char *pmem = mmap(NULL, len,
PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);
if (pmem == MAP_FAILED) {
perror("mmap failed");
close(fd);
return -1;
}
return fd;
}
六、关键参数解析
1. 分辨率参数说明
参数 | 说明 |
---|
xres / yres | 物理屏幕实际分辨率 |
xres_virtual | 虚拟水平分辨率(包含不可见区域) |
yres_virtual | 虚拟垂直分辨率(用于多缓冲) |
2. 位深度处理策略
#define RGB888_FMT 32
#define RGB565_FMT 16
// 根据系统配置自动适配
if (vinf.bits_per_pixel != RGB888_FMT &&
vinf.bits_per_pixel != RGB565_FMT) {
fprintf(stderr, "Unsupported pixel format: %dbpp\n",
vinf.bits_per_pixel);
exit(EXIT_FAILURE);
}
七、像素绘制实现
1. 通用绘制函数
void draw_point(int x, int y, unsigned int col) {
// 边界检查(物理分辨率)
if (x >= vinf.xres || y >= vinf.yres || x < 0 || y < 0)
return;
// 计算内存偏移(使用虚拟分辨率作为跨距)
unsigned int offset = y * vinf.xres_virtual + x;
switch (vinf.bits_per_pixel) {
case RGB888_FMT: // 32-bit (通常带8位alpha通道)
*((unsigned int *)pmem + offset) = col;
break;
case RGB565_FMT: // 16-bit RGB格式
*((unsigned short *)pmem + offset) = (col & 0xFFFF);
break;
default:
break;
}
}
八、颜色格式处理
1. RGB888 颜色编码
// 颜色构造宏(ARGB8888)
#define COLOR_ARGB(a, r, g, b) \
(((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
// 示例颜色定义
#define RED COLOR_ARGB(0xFF, 0xFF, 0x00, 0x00)
#define GREEN COLOR_ARGB(0xFF, 0x00, 0xFF, 0x00)
#define BLUE COLOR_ARGB(0xFF, 0x00, 0x00, 0xFF)
2. RGB565 颜色转换
// RGB888转RGB565
unsigned short rgb888_to_565(unsigned int color) {
unsigned char r = (color >> 16) & 0xFF;
unsigned char g = (color >> 8) & 0xFF;
unsigned char b = color & 0xFF;
return ((r >> 3) << 11) |
((g >> 2) << 5) |
(b >> 3);
}