Linux DRM ( DRI ) 无法像以前一样使用 FBDEV 筛选 /dev/fb0
Posted
技术标签:
【中文标题】Linux DRM ( DRI ) 无法像以前一样使用 FBDEV 筛选 /dev/fb0【英文标题】:Linux DRM ( DRI ) Cannot Screen Scrape /dev/fb0 as before with FBDEV 【发布时间】:2016-05-16 16:53:49 【问题描述】:在其他使用 FBDEV 驱动程序(Raspberry Pi.. 等)的 Linux 机器上,我可以映射 /dev/fb0 设备并直接创建一个 BMP 文件来保存屏幕上的内容。
现在,我正在尝试在 TI Sitara AM57XX (Beagleboard X-15) 上使用 DRM 做同样的事情。用于使用 FBDEV 的代码如下所示。
这个 mmap 似乎不再适用于 DRM。我正在使用带有 Qt 平台 linuxfb 插件的非常简单的 Qt5 应用程序。它可以很好地绘制到 /dev/fb0 并正确显示在屏幕上,但是我无法使用内存映射指针从 /dev/fb0 读回并将屏幕图像保存到文件中。它看起来像这样乱码:
代码:
#ifdef FRAMEBUFFER_CAPTURE
repaint();
QCoreApplication::processEvents();
// Setup framebuffer to desired format
struct fb_var_screeninfo var;
struct fb_fix_screeninfo finfo;
memset(&finfo, 0, sizeof(finfo));
memset(&var, 0, sizeof(var));
/* Get variable screen information. Variable screen information
* gives information like size of the image, bites per pixel,
* virtual size of the image etc. */
int fbFd = open("/dev/fb0", O_RDWR);
int fdRet = ioctl(fbFd, FBIOGET_VSCREENINFO, &var);
if (fdRet < 0)
qDebug() << "Error opening /dev/fb0!";
close(fbFd);
return -1;
if (ioctl(fbFd, FBIOPUT_VSCREENINFO, &var)<0)
qDebug() << "Error setting up framebuffer!";
close(fbFd);
return -1;
else
qDebug() << "Success setting up framebuffer!";
//Get fixed screen information
if (ioctl(fbFd, FBIOGET_FSCREENINFO, &finfo) < 0)
qDebug() << "Error getting fixed screen information!";
close(fbFd);
return -1;
else
qDebug() << "Success getting fixed screen information!";
//int screensize = var.xres * var.yres * var.bits_per_pixel / 8;
//int screensize = var.yres_virtual * finfo.line_length;
//int screensize = finfo.smem_len;
int screensize = finfo.line_length * var.yres_virtual;
qDebug() << "Framebuffer size is: " << var.xres << var.yres << var.bits_per_pixel << screensize;
int linuxFbWidth = var.xres;
int linuxFbHeight = var.yres;
int location = (var.xoffset) * (var.bits_per_pixel/8) +
(var.yoffset) * finfo.line_length;
// Perform memory mapping of linux framebuffer
char* frameBufferMmapPixels = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbFd, 0);
assert(frameBufferMmapPixels != MAP_FAILED);
QImage toSave((uchar*)frameBufferMmapPixels,linuxFbWidth,linuxFbHeight,QImage::Format_ARGB32);
toSave.save("/usr/bin/test.bmp");
sync();
#endif
这是代码运行时的输出:
Success setting up framebuffer!
Success getting fixed screen information!
Framebuffer size is: 800 480 32 1966080
这是显示像素格式的 fbset 的输出:
mode "800x480"
geometry 800 480 800 480 32
timings 0 0 0 0 0 0 0
accel true
rgba 8/16,8/8,8/0,8/24
endmode
root@am57xx-evm:~#
【问题讨论】:
看起来您的帧缓冲区尺寸和/或像素格式已关闭。你能打印出来吗? 我运行 fbset 并将输出附加到问题中。 Alpha 通道有 24 位偏移量,因此它应该是 ARGB32。 我也觉得奇怪的是帧缓冲区大小被指定为 1966080,但 800*480*4 是 1536000。1024*480*4==1966080
所以也许有一些填充。
谢谢 - 每行都被填充以适应 1024 的步长。这解决了我的问题。如果你在下面回答,我会投赞成票。
【参考方案1】:
finfo.line_length
给出实际物理扫描线的大小(以字节为单位)。它不一定等于屏幕宽度乘以像素大小,因为可能会填充扫描线。
但是,您使用的 QImage 构造函数假定没有填充。
如果 xoffset 为零,则应该可以使用带有 bytesPerLine 参数的构造函数直接从帧缓冲区数据构造 QImage。否则有两种选择:
分配一个单独的缓冲区并仅将每个扫描线的可见部分复制到其中 从整个缓冲区(包括填充)创建图像,然后对其进行裁剪【讨论】:
【参考方案2】:如果您使用的是 DRM,那么 /dev/fb0 可能指向一个完全不同的缓冲区(不是当前可见的缓冲区)或具有不同的格式。
fbdev 仅适用于尚未移植 DRM/KMS 的旧遗留系统 并且只有非常有限的 modsetting 功能。
顺便说一句:您使用的是哪个内核?希望不是那个古老而破碎的 TI 供应商内核......
【讨论】:
以上是关于Linux DRM ( DRI ) 无法像以前一样使用 FBDEV 筛选 /dev/fb0的主要内容,如果未能解决你的问题,请参考以下文章