目标:我正在为帧缓冲区编写一个非常简单的图像查看器/dev/fb0
(类似于联邦调查局)。
当前状态:
/sys/class/graphics/fb0/virtual_size
我的软件从(例如)中获取像素分辨率1920,1080
。- 然后(对于每一行)它将为每 1920 个行像素(总共 4x1920=7680 字节)写入 4 个字节(BGRA)到
/dev/fb0
.这在我的一台分辨率为 1920x1080 的笔记本电脑上运行得非常好。 - 更准确地说:在
y
-rowx
-col =>处设置一个像素,其中arr[y * 1920 * 4 + x * 4 + channel]
值为(分别为、、和)。channel
0,1,2,3
B
G
R
A
问题:
当我在旧笔记本电脑上使用(/sys/.../virtual_size
->1366,768
分辨率)尝试相同的软件时,图像未正确显示(有点倾斜)。所以我研究了像素宽度值,发现该值是第1376章(不是 1366)。
问题:
- 这10个额外的字节从哪里来?
- 并且,我怎样才能在不同的机器上获得这个10个额外字节的值(自动,而不是手动调整它)?
- 为什么有些机器需要这额外的 10 个字节,而有些机器不需要它们?
答案1
以编程方式,要检索有关帧缓冲区的信息,您应该使用和sFBIOGET_FSCREENINFO
FBIOGET_VSCREENINFO
ioctl
:
#include <fcntl.h>
#include <linux/fb.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
int main(int argc, char **argv) {
struct fb_fix_screeninfo fix;
struct fb_var_screeninfo var;
int fb = open("/dev/fb0", O_RDWR);
if (fb < 0) {
perror("Opening fb0");
exit(1);
}
if (ioctl(fb, FBIOGET_FSCREENINFO, &fix) != 0) {
perror("FSCREENINFO");
exit(1);
}
if (ioctl(fb, FBIOGET_VSCREENINFO, &var) != 0) {
perror("VSCREENINFO");
exit(1);
}
printf("Line length: %ld\n", fix.line_length);
printf("Visible resolution: %ldx%ld\n", var.xres, var.yres);
printf("Virtual resolution: %ldx%ld\n", var.xres_virtual, var.yres_virtual);
}
line_length
为您提供行步幅。
答案2
行跨步不必与宽度;在您的 1920 宽屏幕上,您的软件只是“偶然”工作了(这并不是偶然,步幅通常是根据硬件对齐要求选择的,而 1920 已经可以被 16 整除,这是一个常见的对齐要求)。
由于不熟悉良好的 ole Linux 帧缓冲区基础设施,我无法直接告诉您如何做到这一点,但您需要弄清楚步幅。
Linux 只是记录行按 16 的倍数对齐,因此您总是需要将宽度四舍五入到下一个倍数,或者 /sys/class/graphics/fb0/ 包含定义步幅的不同虚拟文件,或行对齐。