获取EGL DRM / KMS应用程序的屏幕截图

时间:2017-11-22 07:00:54

标签: linux qt ubuntu opengl egl

如何以编程方式获取图形应用程序的屏幕截图?应用程序通过DRM / KMS使用EGL API绘制窗口。

我使用Ubuntu Server 16.04.3和使用Qt 5.9.2和EGLFS QPA后端编写的图形应用程序。它从第一个虚拟终端(如果有关系)开始,然后将显示切换到全高清图形模式输出。

当我使用在fb2png上运行的实用程序(例如/dev/fb?)时,只保存第一个虚拟终端的文本模式内容( Ctrl + Alt + F1 )作为屏幕截图

很难有EGL API从另一个进程的上下文中获取任何缓冲区的内容(这将是不安全的),但也许有一些机制(和库)可以访问GPU的最终输出? / p>

2 个答案:

答案 0 :(得分:2)

  1. 一种方法是从应用程序中获取屏幕截图,使用glReadPixels()读取后台缓冲区的内容。或者使用QQuickWindow::grabWindow(),其内部以正确的方式使用glReadPixels()。这似乎不适合您,因为您需要在Qt应用程序被冻结时截取屏幕截图。

  2. 另一种方法是使用DRM API映射帧缓冲区,然后memcpy映射的像素。这是使用Python在Chromium OS中实现的,可以轻松地转换为C,请参阅https://chromium-review.googlesource.com/c/chromiumos/platform/factory/+/367611。除了执行渲染的Qt UI进程之外,其他进程也可以使用DRM API。

答案 1 :(得分:1)

这是一个非常有趣的问题,我从多个角度对此问题进行了斗争。

问题非常复杂,并且取决于平台,您似乎正在EGL上运行,这意味着是嵌入式的,除非平台提供这些选项,否则您几乎没有其他选择。

您有以下选择:

glTexSubImage2D

glTexSubImage2D可以将几种缓冲区从OpenGL纹理复制到CPU内存。不幸的是,在GLES 2/3中不受支持,但是您的嵌入式提供商可能会通过扩展来支持它。这很好,因为您可以渲染到FBO或从所需的特定纹理中获取像素。它还需要最少的代码转换。

glReadPixels

glReadPixels是下载已渲染的全部或部分GPU像素的最常用方法。尽管速度很慢,但它可以在GLES和Desktop上运行。在具有良好GPU的台式机上,可以承受交互式帧频,但是要小心,在嵌入式平台上,它可能会确实缓慢,因为它会停止渲染线程获取数据(确保了惊人的帧丢失)。您可以保存代码,因为只需最少的代码修改即可使其工作。

像素缓冲区对象(PBO)

一旦您开始进行真正的研究,PBO's就会出现在这里和那里,因为它们可以异步工作。嵌入式通常也不支持它们,但是即使在中等GPU上,它们也可以在台式机上很好地工作。设置还有些棘手,需要进行特定的渲染修改。

帧缓冲

在嵌入式中,有时您已经渲染到帧缓冲区,所以去那里获取像素。也可以在桌面上使用。您可以将mmap()缓冲区放入文件中,并轻松获取部分内容。但是请注意,在许多嵌入式系统中,EGL不能在帧缓冲区上工作,而可以在不同的“叠加层”上工作,因此您可能需要快照其背景。还要注意,某些多媒体应用程序是在EGL上使用UI并在帧缓冲区上使用媒体播放器来运行的。因此,如果您只需要捕获视频播放器,则可能对您有用。在其他情况下,可以使用EGL定位到复制到帧缓冲区的纹理,它也可以正常工作。

据我所知,渲染到纹理并流到帧缓冲区是他们制作Ableton Push 2所见的甜美Qt UI的方式 enter image description here

更多奇异的Dispmanx / OpenWF

在某些嵌入式系统(尤其是Raspberry Pi和大多数Broadcom Videocore的系统)上,您具有DispmanX。 Whichs is really interesting

这很有趣:

访问GPU的最低级别似乎是通过名为Dispmanx [...]的API进行的。

它继续...

仅是给您完全避免使用Dispmanx的鼓励,几乎没有任何示例,也没有认真的文档。

基本上DispmanX非常接近裸机。因此,它甚至比帧缓冲区或EGL更深。真的很有趣,因为您可以使用vc_dispmanx_snapshot()并真正快速地获取所有内容的快照。快速来说,我的意思是我获得了30FPS RGBA32屏幕捕获,屏幕上没有明显的卡顿现象,并且在Rasberry Pi上大约有4〜6%的额外CPU开销。白天和黑夜都是因为glReadPixels即使在进行1x1像素捕获时也会产生非常明显的帧下降。

这就是我所发现的。